Reputation: 9823
Given this structure, how would I find the object with the given id in this deeply nested object structure.
const menuItems = [
{
id: 1,
imageUrl: "http://placehold.it/65x65",
display: "Shop Women",
link: "#",
type: "image",
nextItems: [
{
id: 10,
display: "홈",
link: "#",
type: "menuitem"
},
{
id: 20,
display: "의류",
link: "#",
type: "menuitem-withmore",
nextItems: [
{
id: 100,
display: "I'm inside one nest",
link: "#",
type: "menuitem"
}
]
},
{
id: 30,
display: "가방",
link: "#",
type: "menuitem-withmore",
nextItems: []
},
{
id: 40,
display: "신발",
link: "#",
type: "menuitem-withmore",
nextItems: []
},
{
id: 50,
display: "악세서리",
link: "#",
type: "menuitem-withmore",
nextItems: []
},
{
id: 60,
display: "SALE",
link: "#",
type: "menuitem-withmore",
style: "bold",
nextItems: []
},
{
id: 70,
display: "브랜드",
link: "#",
type: "menuitem-withmore",
nextItems: []
},
{
type: "separator"
},
{
id: 80,
display: "위시리스트",
link: "#",
type: "menuitem"
},
{
id: 90,
display: "고객센터",
link: "#",
type: "menuitem"
},
{
id: 99,
display: "앱 다운로드",
link: "#",
type: "menuitem"
}
]
},
{
id: 2,
imageUrl: "http://placehold.it/65x65",
display: "Shop Men",
link: "#",
type: "image",
nextItems: [
{
id: 95,
display: "MEN's ITEMS.",
link: "#",
type: "menuitem"
}
]
}
];
Let's say I want to find the object with id: 20
and return this:
{
id: 20,
display: "의류",
link: "#",
type: "menuitem-withmore",
nextItems: [
{
id: 100,
display: "I'm inside one nest",
link: "#",
type: "menuitem"
}
]
},
I can't seem to find how to use lodash for this, and there's this package that may have solved my issue but I couldn't understand how to make it work for my use case.
https://github.com/dominik791/obj-traverse
Upvotes: 1
Views: 6305
Reputation: 726
You may try this function, it will work with a dynamic change of the deep level
function findNodeById(nodes, id, callback?) {
let res;
function findNode(nodes, id) {
for (let i = 0; i < nodes.length; i++) {
if (nodes[i].id === id) {
res = nodes[i];
// you can also use callback back here for more options ;)
// callback(nodes[i]);
break;
}
if (nodes[i].nextItems) {
findNode(nodes[i].nextItems, id);
}
}
}
findNode(nodes, id)
return res;
}
findNodeById(menuItems, 99) // { id: 99, display: "앱 다운로드", link: "#", type: "menuitem" }
Upvotes: 2
Reputation: 1162
Maybe this helps
menuItems.map(item => {
if (item.id === 10) return item;
});
BTW I didn't consider efficiency in this solution.
Upvotes: 1
Reputation: 721
I would do it
const menuItems = [
{
id: 1,
imageUrl: "http://placehold.it/65x65",
display: "Shop Women",
link: "#",
type: "image",
nextItems: [
{
id: 10,
display: "홈",
link: "#",
type: "menuitem"
},
{
id: 20,
display: "의류",
link: "#",
type: "menuitem-withmore",
nextItems: [
{
id: 100,
display: "I'm inside one nest",
link: "#",
type: "menuitem"
}
]
},
{
id: 30,
display: "가방",
link: "#",
type: "menuitem-withmore",
nextItems: []
},
{
id: 40,
display: "신발",
link: "#",
type: "menuitem-withmore",
nextItems: []
},
{
id: 50,
display: "악세서리",
link: "#",
type: "menuitem-withmore",
nextItems: []
},
{
id: 60,
display: "SALE",
link: "#",
type: "menuitem-withmore",
style: "bold",
nextItems: []
},
{
id: 70,
display: "브랜드",
link: "#",
type: "menuitem-withmore",
nextItems: []
},
{
type: "separator"
},
{
id: 80,
display: "위시리스트",
link: "#",
type: "menuitem"
},
{
id: 90,
display: "고객센터",
link: "#",
type: "menuitem"
},
{
id: 99,
display: "앱 다운로드",
link: "#",
type: "menuitem"
}
]
},
{
id: 2,
imageUrl: "http://placehold.it/65x65",
display: "Shop Men",
link: "#",
type: "image",
nextItems: [
{
id: 95,
display: "MEN's ITEMS.",
link: "#",
type: "menuitem"
}
]
}
];
var data = [];
menuItems.forEach(function(item) {
item.nextItems.forEach(function(element) {
data.push(element)
}, this);
}, this);
console.log(_.where(data, {id: 20}));
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
Upvotes: 1
Reputation: 1202
If you're using lodash, you just want the .find(collection, [predicate=.identity]).
So you'd want something like so:
_.find(menuItems, function(item) {
return item.id = 20;
});
Upvotes: -4
Reputation: 2720
Use DFS.
const menuItems = [
{
id: 1,
imageUrl: "http://placehold.it/65x65",
display: "Shop Women",
link: "#",
type: "image",
nextItems: [
{
id: 10,
display: "홈",
link: "#",
type: "menuitem"
},
{
id: 20,
display: "의류",
link: "#",
type: "menuitem-withmore",
nextItems: [
{
id: 100,
display: "I'm inside one nest",
link: "#",
type: "menuitem"
}
]
},
{
id: 30,
display: "가방",
link: "#",
type: "menuitem-withmore",
nextItems: []
},
{
id: 40,
display: "신발",
link: "#",
type: "menuitem-withmore",
nextItems: []
},
{
id: 50,
display: "악세서리",
link: "#",
type: "menuitem-withmore",
nextItems: []
},
{
id: 60,
display: "SALE",
link: "#",
type: "menuitem-withmore",
style: "bold",
nextItems: []
},
{
id: 70,
display: "브랜드",
link: "#",
type: "menuitem-withmore",
nextItems: []
},
{
type: "separator"
},
{
id: 80,
display: "위시리스트",
link: "#",
type: "menuitem"
},
{
id: 90,
display: "고객센터",
link: "#",
type: "menuitem"
},
{
id: 99,
display: "앱 다운로드",
link: "#",
type: "menuitem"
}
]
},
{
id: 2,
imageUrl: "http://placehold.it/65x65",
display: "Shop Men",
link: "#",
type: "image",
nextItems: [
{
id: 95,
display: "MEN's ITEMS.",
link: "#",
type: "menuitem"
}
]
}
];
function dfs(obj, targetId) {
if (obj.id === targetId) {
return obj
}
if (obj.nextItems) {
for (let item of obj.nextItems) {
let check = dfs(item, targetId)
if (check) {
return check
}
}
}
return null
}
let result = null
for (let obj of menuItems) {
result = dfs(obj, 100)
if (result) {
break
}
}
console.dir(result)
Upvotes: 12