【问题标题】:How to get the value of each parent from a nested array of object如何从嵌套的对象数组中获取每个父级的值
【发布时间】:2021-10-27 11:43:55
【问题描述】:

所以我有多个对象数组,每个对象都包含一个子对象。

例如

const data = [
    {
        id: 1,
        name: 'parent 1',
        children: [
            {
                id: 'c1',
                name: 'child 1',
                children: [
                    {
                        id: 'g1',
                        name: 'grand 1',
                        children: [],
                    },
                ],
            },
        ],
    },
    {
        id: 2,
        name: 'parent 2',
        children: [
            {
                id: 2,
                name: 'c1',
                children: [],
            },
        ],
    },
    { id: 3, name: 'parent 3', children: [] },
];

我想要发生的是,如果我正在搜索的 Id 是 'g1',我会得到结果

const result = ['parent 1', 'c1', 'grand 1']

循环只会停止并获取它通过的所有名称,直到满足条件(在本例中为 id)

当前方法已完成

/**
 * Details
 * @param id the value you are searching for
 * @param items nested array of object that has child
 * @param key name of the value you are looking for
 * @returns string of array that matches the id
 * @example ['parent 1', 'c1', 'grand 1']
 */
export function findAll(id: string, items: any, key: string): string[] {
  let i = 0;
  let found;
  let result = [];

  for (; i < items.length; i++) {
    if (items[i].id === id) {
      result.push(items[i][key]);
    } else if (_.isArray(items[i].children)) {
      found = findAll(id, items[i].children, key);
      if (found.length) {
        result = result.concat(found);
      }
    }
  }
  return result;
}

【问题讨论】:

  • 你试过什么?另外,const result = 'parent 1' &gt; 'c1' &gt; 'grand 1'这是无效的数据对象,你可以验证你想要什么数据结构。
  • @ikhvjs,我更新了我想看的结果,谢谢评论
  • 到目前为止你尝试过什么?我认为递归函数方法适合您的情况。
  • @ikhvjs,我尝试了这个,第三个答案,stackoverflow.com/questions/30714938/… 并进行了一些修改,但我似乎找不到将父母姓名存储在结果数组中的方法
  • 你能告诉我们你的方法吗?

标签: javascript arrays typescript object


【解决方案1】:

我编写了这段迭代代码,可能会对您有所帮助。它基本上遍历存储从顶层到所需id的路径的结构:

function getPath(obj, id) {
    // We need to store path
    // Start stack with root nodes
    let stack = obj.map(item => ({path: [item.name], currObj: item}));
    while (stack.length) {
        const {path, currObj} = stack.pop()
        if (currObj.id === id) {
            return path;
        } else if (currObj.children?.length) {
            stack = stack.concat(currObj.children.map(item => ({path: path.concat(item.name), currObj: item})));
        }
    }
    return null; // if id does not exists
}

此代码假定您的结构是正确的并且没有遗漏任何部分(除了可以为 null 的子代)。 顺便说一句,你的答案正确吗?我想路径应该是: ["parent 1", "child 1", "grand 1"]

【讨论】:

    【解决方案2】:

    下面的解决方案是执行搜索的递归函数。

    const data = [
        {
            id: 1,
            name: 'parent 1',
            children: [
                {
                    id: 'c1',
                    name: 'child 1',
                    children: [
                        {
                            id: 'g1',
                            name: 'grand 1',
                            children: [],
                        },
                    ],
                },
            ],
        },
        {
            id: 2,
            name: 'parent 2',
            children: [
                {
                    id: 2,
                    name: 'c1',
                },
            ],
        },
        { id: 3, name: 'parent 3', children: [{}] },
    ];
    
    function getPath(object, search) {
        if (object.id === search) return [object.name];
        else if ((object.children) || Array.isArray(object)) {
            let children = Array.isArray(object) ? object : object.children;
            for (let child of children) {
                let result = getPath(child, search);
                if (result) {
                    if (object.id )result.unshift(object.name);
                    return result;
                }
            }
        }
    }
    
    //const result = ['parent 1', 'c1', 'grand 1']
    const result = getPath(data, 'g1');
    console.log(result);

    【讨论】:

    • 嗨 Lajos,当数据结构中只有一个“g1”时,它工作正常。如果在另一组 JSON 中的最后一个子节点中存在相同的“g1”怎么办。我的数据结构中没有名为 id 的单独键。我可能有重复的数据。现在如何提取我想要的确切数据集。?
    • @JohnsonAnthony 我对您的问题的理解是您有一个没有id 的 JSON,并且您可能有重复的结果。如果我正确理解您的问题,那么您想找到所有匹配项。这是一个准确的理解吗?另外,您可以创建一个 JSFiddle 并在评论部分分享链接,或者提出一个单独的问题并在评论部分分享链接?如果您今天创建它,那么我可能会在今天或明天研究它。
    【解决方案3】:

    您可以编写一个递归函数,在将遍历的对象累积到堆栈中时遍历数组。一旦你得到一个带有你想要(id == g1) 的 id 的对象,你就可以打印解决方案。可能是这样的:

    'use strict';
    
    function print(stack) {
        //console.log("Printing result...\n");
        let result = "";
        stack.forEach(element => {
            result += element["name"] + " > ";
        });
        console.log(result + "\n");
    }
    
    function walkThrough(data, id, stack) {
        if (data !== undefined)
        for (let i = 0; i < data.length; i++) {
            const element = data[i];
            //console.log("Going through " + element["name"] + " with id == " + element["id"]);
            stack.push(element);
            if (element["id"] == id) print(stack);
            else walkThrough(element["children"], id, stack);            
        }
    }
    
    const data = [
        {
            "id": 1,
            "name": 'parent 1',
            "children": [
                {
                    "id": 'c1',
                    "name": 'child 1',
                    "children": [
                        {
                            "id": 'g1',
                            "name": 'grand 1',
                            "children": [],
                        },
                    ],
                },
            ],
        },
        {
            "id": 2,
            "name": 'parent 2',
            "children": [
                {
                    "id": 2,
                    "name": 'c1',
                },
            ],
        },
        { "id": 3, "name": 'parent 3', "children": [{}] },
    ];
    //Calling the function to walk through the array...
    walkThrough(data, 'g1', []);
    

    【讨论】:

      【解决方案4】:

      另一种方法(不像上述解决方案那么优雅,但也可以)

      非常直接:
      使用for 迭代循环到第 3 级,当在第 3 级找到孙子时,break 以逃避所有 3 级。

      我很好奇不同的解决方案如何比较大型数据集(比如一百万条记录)的性能。

      let i=0, k=0, l=0;
      
      let childrenLength = 0, grandChildrenLength = 0;
      
      let result = [];
      let foundGrandChild = false;
      
      function searchGrandChild(searchString) {
      
        for (i; i< data.length; ++i) {
          if(data.length > 0){
            childrenLength = data[i].children.length;
      
            if(childrenLength > 0) {
              for (k; k < childrenLength; ++k) {
      
                if(data[i].children[k] != undefined) {
                  grandChildrenLength = data[i].children[k].children.length;
      
                  if(grandChildrenLength > 0) {
                    for (l; l < grandChildrenLength; ++l) {
                      if(data[i].children[k].children[l] != undefined) {
      
                        if(data[i].children[k].children[l].id === searchString) {
                          result.push(data[i].name);
                          result.push(data[i].children[k].id);
                          result.push(data[i].children[k].children[l].name);
                          foundGrandChild = true;
                          console.log('Yap, we found your grandchild ?')
                          console.log(result);
                          break;
                        }
                      }
                      if(foundGrandChild) break;
                    }
      
                  }
                }
                if(foundGrandChild) break;
              }
      
            }
          }
          if(foundGrandChild) break;
        }
      
        if(!foundGrandChild) console.log('sorry, we could not find your grandchild ?')
      };
      
      const data = [
          {
              id: 1,
              name: 'parent 1',
              children: [
                  {
                      id: 'c1',
                      name: 'child 1',
                      children: [
                          {
                              id: 'g1',
                              name: 'grand 1',
                              children: [],
                          },
                      ],
                  },
              ],
          },
          {
              id: 2,
              name: 'parent 2',
              children: [
                  {
                      id: 2,
                      name: 'c1',
                  },
              ],
          },
          { id: 3, name: 'parent 3', children: [{}] },
      ];
      
      
      console.log('Let us search for "g1" ...');
      searchGrandChild('g1');
      
      console.log('Let us now search for "g2" ...');
      foundGrandChild = false;
      searchGrandChild('g2');

      【讨论】:

        猜你喜欢
        • 2021-11-29
        • 1970-01-01
        • 2015-03-13
        • 1970-01-01
        • 2021-09-21
        • 2020-05-10
        • 2013-10-11
        • 2019-11-20
        • 1970-01-01
        相关资源
        最近更新 更多