【问题标题】:How to find object with id value in deep nested array?如何在深层嵌套数组中查找具有 id 值的对象?
【发布时间】:2018-03-15 20:19:20
【问题描述】:

给定这个结构,我如何在这个深度嵌套的对象结构中找到具有给定 id 的对象。

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"
            }
        ]
    }
];

假设我想用id: 20 找到对象并返回:

        {
            id: 20,
            display: "의류",
            link: "#",
            type: "menuitem-withmore",
            nextItems: [
                {
                    id: 100,
                    display: "I'm inside one nest",
                    link: "#",
                    type: "menuitem"
                }
            ]
        },

我似乎找不到如何使用 lodash,并且有这个包可能已经解决了我的问题,但我不明白如何使它适用于我的用例。

https://github.com/dominik791/obj-traverse

【问题讨论】:

  • 您要在menuListnextItems 中查找该项目吗?
  • 正是我在退货示例中发布的内容。该对象以及它可能拥有的任何子对象,例如 nextItems。
  • @JoeLafiosca 不是骗子——他的问题和答案只涉及 1 级深度。
  • findAll 答案的深度超过 1 级,但无论如何都适用相同的迭代原则。如果您想推出自己的解决方案,您可以使用递归,如下面的 Kevin Qian 的 DFS 回答中所示。

标签: javascript object find lodash


【解决方案1】:

使用 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)

【讨论】:

  • 什么是 DFS?那是一个库还是什么?
  • @SergioTapia Depth First Search,一种基本算法,基本上递归尽可能深,如果没有找到,就回溯一层,再寻找下一层,直到找到。见en.wikipedia.org/wiki/Depth-first_search
  • 如果我们在谈论算法,为什么不直接使用二叉搜索树呢?我认为我的 lodash 答案很简单,但似乎没有人喜欢。
【解决方案2】:

你可以试试这个功能,它会随着深层次的动态变化而工作

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" }

【讨论】:

    【解决方案3】:

    我愿意

    		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}));
    &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"&gt;&lt;/script&gt;

    【讨论】:

      【解决方案4】:

      也许这有帮助

      menuItems.map(item => {
          if (item.id === 10) return item;
      });
      

      顺便说一句,我没有考虑这个解决方案的效率。

      【讨论】:

        【解决方案5】:

        如果您使用 lodash,您只需要 .find(collection, [predicate=.identity])。
        所以你会想要这样的东西:

        _.find(menuItems, function(item) {
           return item.id = 20;
        });
        

        【讨论】:

        • 这是否深入了解所有内容?如果是这样,这太好了,不可能是真的哈哈
        • 项目本身是另一个集合。有很多功能可以用来拉出任何你想要的东西。 _.get,帮助处理空引用,_.find 等。我不知道为什么我在这里得到了负滴答。但是你说lodash所以我尝试了。大声笑,欢迎来到 StackOverflow 任何角色都很重要的地方大声笑
        猜你喜欢
        • 2020-12-10
        • 2020-04-13
        • 2019-07-18
        • 2018-03-01
        • 2019-04-08
        • 1970-01-01
        • 1970-01-01
        • 2018-02-14
        • 2021-11-21
        相关资源
        最近更新 更多