【问题标题】:How to loop through complex JSON tree data?如何遍历复杂的 JSON 树数据?
【发布时间】:2020-12-21 04:00:59
【问题描述】:

问题:我收到的 JSON 树数据如下所示:

let TREE_DATA = {
  items: [
    {
      id: '1',
      name: 'alpha',
    },
    {
      id: '2',
      name: 'bravo',
      children: [
        {
          id: '3',
          name: 'charlie',
        },
        {
          id: '4',
          name: 'delta',
        },
        {
          id: '5',
          name: 'emmet',
          children: [
            {
              id: '6',
              name: 'franklin',
            },
            {
              id: '7',
              name: 'glove',
              children: [
                {
                  id: '8',
                  name: 'eight',
                },
                {
                  id: '9',
                  name: 'nine',
                },
              ],
            },
            {
              id: '10',
            },
          ],
        },
        {
          id: '11',
        },
        {
          id: '12',
        },
      ],
    },
    {
      id: '13',
    },
    {
      id: '14',
    },
  ],
};

目标是获取 json 对象及其 id 并找到与 id 匹配的对象。 让我们假设它已被解析,因此它被视为一个对象。

基本上,我不知道每组id和name嵌套的深度。

所以我知道我可能会想出某种递归来继续挖掘它的基础 直到没有孩子。

通常,如果它是一个数组,我会使用 .Map 或 .Reduce 方法来遍历这个问题。

function seek(arr, id) {
   return arr.reduce((a, c) => {
    if (a) return a;
    if (c.id === id) return c;
    if (c.children) return test7(c.children, id);
    if (!(c.id === id)) return a; 
  }, null)
}

由于 JSON 的数据结构有点不同,我给出了以下尝试

function seek(json, id) {
  for (let key in json) {
    for (let el of key) {
      if (el.id === id) {
        return el;
      } else {
        if (el.children) {
          result = test7(el.children, id);
        }
      }
    }
  }
}

我在这里想要完成的是;

seek(TREE_DATA.items, '6') // { "id": "6", "name": "franklin" }

由于这不是一个数组而是一个复杂数据集的对象, 我可能会首先查看对象的键值。 然后我会再次开始循环每个键中的数组,看看哪个匹配。 如果数组中的一个对象有“key”,children,那么我会从头开始这个过程。

我已经通过 chrome 调试了这个,我发现了我的方法中的漏洞。 当在数据集中找到孩子时,它将从头开始整个过程​​。 由于我是先循环遍历对象,所以它将面对一个数组而不是对象中的键。

我的另一个尝试是从对象项中提取数组; 但问题是我真的想不出办法,而且也不是一个好的永久解决方案。

这是我的问题:

  1. 对于此类问题有什么好的方法?
  2. 为了达到我想要的结果,我缺少什么?
  3. 什么是更有效的解决方案?

注意:我是初学者,我正在努力学习材料,而不是寻找“只是一个答案”。如果您能提供一些解释,我将不胜感激。提前致谢。

【问题讨论】:

    标签: javascript arrays json loops


    【解决方案1】:

    处理 items 的方式与处理 children 数组的方式相同 - 如果 ID 匹配,则使用递归函数返回顶级对象之一,如果找到 children 属性,则递归调用自身:

    let TREE_DATA={items:[{id:"1",name:"alpha"},{id:"2",name:"bravo",children:[{id:"3",name:"charlie"},{id:"4",name:"delta"},{id:"5",name:"emmet",children:[{id:"6",name:"franklin"},{id:"7",name:"glove",children:[{id:"8",name:"eight"},{id:"9",name:"nine"}]},{id:"10"}]},{id:"11"},{id:"12"}]},{id:"13"},{id:"14"}]};
    
    const findObj = (arr, idToFind) => {
      for (const item of arr) {
        if (item.id === idToFind) return item;
        if (item.children) {
          const recursiveResult = findObj(item.children, idToFind);
          if (recursiveResult) return recursiveResult;
        }
      }
    };
    console.log(findObj(TREE_DATA.items, '14'));
    console.log(findObj(TREE_DATA.items, '11'));

    我认为像上面那样使用for 循环比reduce 更好,因为如果找到匹配项,for 循环可以立即终止(而不是必须先遍历其他项目)。

    由于您感兴趣的键 (id) 和递归结构属性名称 (children) 在整个数据结构中都是相同的,因此无需遍历键名 - 只需遍历数组即可。

    【讨论】:

    • 感谢您的详细解释。我完全错过了您可以简单地将 obj.items 提供给参数。所以对于这个特殊的问题,你是正确的。如果您不介意其他问题,与这个特定问题不同,在您有多个对象的情况下您会怎么做?例如,现在 json 只有键“items”,但在具有不同键的对象中。
    • 检查您要测试的条件的不同键?例如if (item.id === idToFind || item.name === nameToFind)
    猜你喜欢
    • 2019-11-08
    • 1970-01-01
    • 1970-01-01
    • 2018-11-21
    • 2021-07-29
    • 1970-01-01
    • 2020-04-05
    • 1970-01-01
    相关资源
    最近更新 更多