Sergio Tapia
Sergio Tapia

Reputation: 9823

How to find object with id value in deep nested array?

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

Answers (5)

Ihor
Ihor

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

null
null

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

Max Ferreira
Max Ferreira

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

Dylan Wright
Dylan Wright

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

Kevin Qian
Kevin Qian

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

Related Questions