【问题标题】:Find an object inside an object在对象内部查找对象
【发布时间】:2021-06-05 15:02:11
【问题描述】:

我目前正在尝试访问一个对象及其属性,但我似乎无法找到一种方法来获取不是其各自子数组中第一项的对象。它只能找到数组中的第一个数字,但我认为我在函数中做错了事情,我不太确定如何修复它。我的错误可能是什么?如何解决?

这是树:

{
    name: "One",
    ids: {
        id: 1,
        level: 0
    },
    children: [
        {
            name: "Two",
            ids: {
                id: 2,
                level: 1
            },
            children: [
                {
                    name: "Three",
                    ids: {
                        id: 3,
                        level: 2
                    },
                    children: [
                        {
                            name: "Five",
                            ids: {
                                id: 5,
                                level: 3
                            },
                            children: [
                                {
                                    name: "Eight",
                                    ids: {
                                        id: 8,
                                        level: 4
                                    },
                                    children: []
                                },
                                {
                                    name: "Nine",
                                    ids: {
                                        id: 9,
                                        level: 4
                                    },
                                    children: []
                                },
                                {
                                    name: "Ten",
                                    ids: {
                                        id: 10,
                                        level: 4
                                    },
                                    children: []
                                }
                            ]
                        }
                    ]
                },
                {
                    name: "Four",
                    ids: {
                        id: 4,
                        level: 2
                    },
                    children: [
                        {
                            name: "Six",
                            ids: {
                                id: 6,
                                level: 3
                            },
                            children: []
                        },
                        {
                            name: "Seven",
                            ids: {
                                id: 7,
                                level: 3
                            },
                            children: []
                        }
                    ]
                }
            ]
        }
    ]
}

这是我的功能:

findObj(obj, id) {
    if(obj.ids.id == id) {
        return obj;
    }
    else if(obj.children.length != 0) {
        for(var i in obj.children) {
            var temp = findObj(obj.children[i], id);
            if(temp != undefined) {
                return temp;
            }
        }
    }
}

【问题讨论】:

    标签: javascript object recursion


    【解决方案1】:

    像这样使用递归函数怎么样

    function findObj(obj, id) {
        let answer
        if(obj.ids.id == id) return obj
        findChildren(obj.children, id)
    
        function findChildren(children, id) {
            for(let i=0;i<children.length;i++) {
                 if(children[i].ids.id === id) return answer = children[i]
                 findChildren(children[i].children, id)
            } 
        }
        return answer
    }
    

    【讨论】:

    • 代码不起作用,但我认为这让我对我的其他功能有了一些想法。谢谢。
    【解决方案2】:

    您可以使用带有单个 forEach 循环的递归方法来执行此操作。

    const data = {"name":"One","ids":{"id":1,"level":0},"children":[{"name":"Two","ids":{"id":2,"level":1},"children":[{"name":"Three","ids":{"id":3,"level":2},"children":[{"name":"Five","ids":{"id":5,"level":3},"children":[{"name":"Eight","ids":{"id":8,"level":4},"children":[]},{"name":"Nine","ids":{"id":9,"level":4},"children":[]},{"name":"Ten","ids":{"id":10,"level":4},"children":[]}]}]},{"name":"Four","ids":{"id":4,"level":2},"children":[{"name":"Six","ids":{"id":6,"level":3},"children":[]},{"name":"Seven","ids":{"id":7,"level":3},"children":[]}]}]}]}
    
    function findObj(obj, id) {
      let result = null;
    
      if (obj.ids.id === id) result = obj;
      if (obj.children) {
        obj.children.forEach(c => {
          if (!result) result = findObj(c, id)
        })
      }
    
      return result;
    }
    
    console.log(findObj(data, 6))
    console.log(findObj(data, 5))
    console.log(findObj(data, 1))

    【讨论】:

    • 代码有效,尽管我对其进行了一些更改。非常感谢。
    【解决方案3】:

    我喜欢将对象遍历与试图查找内容的代码分开。我将使用谓词从对象的详细信息中进一步分离出一个通用的deepFind 函数。

    function * traverse (obj) {
      yield obj;
      for (let child of obj.children) {yield * traverse (child)}
    }
    
    const deepFind = (pred) => (obj) => {
      for (let node of traverse (obj)) {
        if (pred (node)) {return node} 
      }
    }
    
    const findById = (targetId) =>
      deepFind (({ids: {id}}) => id == targetId)
    
    const objs = {name: "One", ids: {id: 1, level: 0}, children: [{name: "Two", ids: {id: 2, level: 1}, children: [{name: "Three", ids: {id: 3, level: 2}, children: [{name: "Five", ids: {id: 5, level: 3}, children: [{name: "Eight", ids: {id: 8, level: 4}, children: []}, {name: "Nine", ids: {id: 9, level: 4}, children: []}, {name: "Ten", ids: {id: 10, level: 4}, children: []}]}]}, {name: "Four", ids: {id: 4, level: 2}, children: [{name: "Six", ids: {id: 6, level: 3}, children: []}, {name: "Seven", ids: {id: 7, level: 3}, children: []}]}]}]}
    
    console .log (findById (5) (objs))
    .as-console-wrapper {max-height: 100% !important; top: 0}

    这里traverse 对您的对象进行了前序遍历(首先是根,然后是分支)。它应该适用于具有children 数组属性的任何对象。 (如果这些可以是可选的,那么解决这个问题就很简单了。)我们在上面写deepFind,接受一个谓词并返回第一个匹配它的节点,或者undefined如果没有。

    那么findById 几乎是微不足道的。我们只需调用 deepFind 并带有一个检查您的 id 条件的谓词。

    我喜欢像findById (5) (objs) 这样的称呼方式。我发现它澄清了很多事情。但如果你更喜欢打电话给findById(objs, 5),那么我们可以改用这个:

    const findById = (obj, targetId) =>
      deepFind (({ids: {id}}) => id == targetId) (obj)
    

    当您需要在第一次匹配时停止的进程时,生成器函数会变得非常有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-18
      • 1970-01-01
      • 2022-01-12
      相关资源
      最近更新 更多