简体   繁体   English

如何循环遍历复杂的 JSON 树数据?

[英]How to loop through complex JSON tree data?

Problem: I am given JSON tree data that looks something like below:问题:我得到 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',
    },
  ],
};

The objective is to take the json object and its id and find matching object with id.目标是获取 json object 及其 id,并找到与 id 匹配的 object。 let's just assume its been parsed so it's treated like an object.让我们假设它已被解析,因此它被视为 object。

Basically, I don't know how deeply each set of id and name is nested.基本上,我不知道每组id和name嵌套的有多深。

So I know I would probably come up with some kind of recursion to keep digging with its base until there's no children.所以我知道我可能会想出某种递归来继续挖掘它的基础,直到没有孩子。

Normally, I would approach this problem with.Map or.Reduce method to iterate through if it was an array.通常,如果它是一个数组,我会使用 .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)
}

Since data structure with JSON is a bit different, I've given following try由于 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);
        }
      }
    }
  }
}

What I am trying to accomplish here is;我在这里想要完成的是;

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

Since this is not an array but an object of complex data sets, I'd probably look into the key value of an object first.由于这不是一个数组,而是一个 object 的复杂数据集,我可能会先查看 object 的键值。 Then I'd once again start looping the array in each key and see which one matches.然后我将再次开始在每个键中循环数组并查看哪个匹配。 If an object in the array has "key", children, then I would start the process from the beginning.如果数组中的 object 有“key”,孩子,那么我会从头开始这个过程。

I have debugged this through chrome, and I found the loop hole in my approach.我已经通过 chrome 调试了这个,我发现了我的方法中的漏洞。 When children is found in a data set, then it would start the whole process from the beginning.当在数据集中找到孩子时,它将从头开始整个过程。 Since I am looping through the object first, it will face an array rather than the keys in object.由于我首先循环遍历 object,它将面对一个数组而不是 object 中的键。

Another attempt I made was to get extract the array out of object items;我做的另一个尝试是从 object 项中提取数组; But the issue is I can't really think of the way, and also it is not a good permanent solution.但问题是我真的想不出办法,也不是一个好的永久解决方案。

Here are my questions:这是我的问题:

  1. What's a good approach for a problem like this?解决这样的问题的好方法是什么?
  2. What am I missing to achieve the result I want?为了达到我想要的结果,我缺少什么?
  3. What would be a more efficient solution to this?什么是更有效的解决方案?

Note: I am a beginner, and I am trying to learn the material rather than looking for “just an answer". I would really appreciate if you could provide some explanation. Thanks in advance.注意:我是初学者,我正在尝试学习材料而不是寻找“只是一个答案”。如果你能提供一些解释,我将不胜感激。提前致谢。

Handle the items way the same way you handle the children array - use a recursive function that returns one of the top-level objects if the ID matches, or calls itself recursively if a children property is found:以与处理children数组相同的方式处理items - 使用递归 function 如果 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'));

I think using a for loop like I did above is a better approach than reduce , because a for loop can terminate immediately if a match is found (rather than having to iterate through other items first).我认为像我上面那样使用for循环是比reduce更好的方法,因为如果找到匹配项, for循环可以立即终止(而不是必须先遍历其他项目)。

Because the key you're interested in ( id ) and the recursive structure property name ( children ) are the same throughout the data structure, there's no need to loop through key names - just loop through the array.因为您感兴趣的键 ( id ) 和递归结构属性名称 ( children ) 在整个数据结构中都是相同的,所以不需要遍历键名 - 只需遍历数组即可。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM