【问题标题】:Iterate though nested object and get obj by value using es6+使用 es6+ 遍历嵌套对象并按值获取 obj
【发布时间】:2019-07-25 05:35:09
【问题描述】:

对于这种结构的对象:

const myObj = {
  id: 1,
  name: '1',
  children: [
    {
      id: 2,
      name: '2',
      children: [
        {
          id: 3,
          name: '3',
          children: []
        }
      ]
    },
    {
      id: 4,
      name: '4',
      children: [
        {
          id: 5,
          name: '5',
          children: [
            {
              id: 6,
              name: '6',
              children: [
                {
                  id: 7,
                  name: '7',
                  children: []
                }
              ]
            }
          ]
        }
      ]
    },
  ]
}

如何通过值 (id) 获取对象?所以我正在寻找一个函数,如果我称之为:

findObj(myObj, 6);

它会返回这个:

       {
          id: 6,
          name: '6',
          children: [
            {
              id: 7,
              name: '7',
              children: []
            }
          ]
        }

另一个例子:

findObj(myObj, 3);

会返回这个:

    {
      id: 3,
      name: '3',
      children: []
    }

我知道我需要一个递归函数。这是我到目前为止所拥有的:

  findObj(obj, id) {
    if (obj.id === id) {
      return obj;
    }

    obj.forEach(x => {
      if (x.id === id) {
        return x;
      } else {
        this.findObj(x.children, id);
      }
    });
  }

(这是一个角度类)

【问题讨论】:

  • 搜索父项具有误导性,因为您搜索的是项目本身。顺便说一句,你试过什么?
  • 是的,我刚刚编辑了我的答案哈哈@NinaScholz
  • 如果您从回调函数中return,请考虑它在父函数中的含义。然后考虑Array#forEach 做了什么。
  • 我在this Q&A 中实现了一个通用的deepFind 解决方案。我想你会发现它很有用:D

标签: javascript recursion


【解决方案1】:

乍一看,我发现了一些问题。

如果您已经在函数中添加了ob.id === id,则以后无需仔细检查。此外,如果findObj 是在作用域中定义的函数,与任何其他变量一样,并且不在“类”定义中,则不需要通过this 调用它,与第一次调用@987654325 的方式相同@你没有this关键字。

另外,首先你将一个对象传递给你的方法,然后你传递一个对象数组(obj.children),然后你检查forEach方法中的id,在那里你传递一个函数( x => { ...thingy),所以当你返回时,你会从那个函数而不是主函数返回。

我已经为你修好了。我建议您了解正在发生的事情并从中学习,因为如果您知道自己在做什么,就不会发生这种情况(这里的调试是您的主人)。

findObj(obj, id) {
    if (obj.id === id) {
        return obj;
    }
    for (var i = 0; i < obj.children.length; i++) { // No forEach, so when we return, we actually return from findObj
        var r = findObj(obj.children[i], id); // We see if we have any return and let the "check logic" be defined on one location instead of duplicated.
        if (r) {
            return r;
        }
    }
}

【讨论】:

  • 也有不错的替代方案,如forEach MDN Documentation中所述:There is no way to stop or break a forEach() loop other than by throwing an exception. If you need such behavior, the forEach() method is the wrong tool.
【解决方案2】:

您可以检查对象或检查子项。

function find(object, id) {
    var result;
    if (object.id === id) return object;
    object.children.some(o => result = find(o, id));
    return result;
}

const object = { id: 1, name: '1', children: [{ id: 2, name: '2', children: [{ id: 3, name: '3', children: [] }] }, { id: 4, name: '4', children: [{ id: 5, name: '5', children: [{ id: 6, name: '6', children: [{ id: 7, name: '7', children: [] }] }] }] }] };

console.log(find(object, 5));
console.log(find(object, 6));
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

    【解决方案3】:

    两个问题:

    • 您的return x; 语句仅从forEach 回调返回,而不是从findObj 函数返回。不要使用forEach!一个简单的for … of 循环就可以了
    • 如果您的递归调用找到对象并返回它,您将忽略它并继续迭代。检查您是否得到结果并妥善处理。

    我猜你不是在寻找一个完整的解决方案,所以我把它作为一个练习:-)

    【讨论】:

      猜你喜欢
      • 2016-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-28
      • 2019-04-24
      • 1970-01-01
      • 1970-01-01
      • 2020-04-28
      相关资源
      最近更新 更多