【问题标题】:Loop through nested JSON child objects遍历嵌套的 JSON 子对象
【发布时间】:2020-02-09 12:46:31
【问题描述】:

我有这个 JSON 有效负载,其中每个对象都包含一个 ID、名称和子数组。这里我需要获取所有元素的 ID,包括根和所有嵌套的子元素。

{
  "_id": "-1",
  "_name": "root",
  "_children": [
    {
      "_id": "1",
      "_name": "Child 1",
      "_children": [
        {
          "_id": "1-1",
          "_name": "Child 1-1",
          "_children": [
            {
              "_id": "1-1-1",
              "_name": "Child 1-1-1",
              "_children": [

              ]
            }
          ]
        },
        {
          "_id": "1-2",
          "_name": "Child 1-2",
          "_children": [

          ]
        },
        {
          "_id": "1-3",
          "_name": "Child 1-3",
          "_children": [

          ]
        }
      ]
    },
    {
      "_id": "2",
      "_name": "Child 2",
      "_children": [
        {
          "_id": "2-2",
          "_name": "Child 2-2",
          "_children": [

          ]
        }
      ]
    }
  ]
}

如何循环获取所有子节点和根节点的 ID 值?

这是我尝试使用嵌套函数的方法,但它不起作用。

getNestedChildren(arr) {
  var out = []
    for(var i in arr[0].children) {
      out.push(arr[i].id);
        if(arr[i].children && arr[i].children.size() > 0) {
            var children = this.getNestedChildren(arr[i].children)
        }
    }

【问题讨论】:

  • 你能显示预期的输出吗?
  • @Mridul [-1, 1, 1-1, 1-1-1, 1-2, 1-3, 2, 2-2]

标签: typescript tree


【解决方案1】:

您可以使用递归并通过引用修改“结果数组”。

例如,如果您的嵌套对象存储在变量data 中,那么:

function addNestedChildrenToArray(obj, resultArray) {
    resultArray.push(obj._id);
    obj._children.forEach(child => addNestedChildrenToArray(child, resultArray));
}

const resultArray = [];
addNestedChildrenToArray(data, resultArray);
// resultArray now contains the results
console.log(resultArray);

You can test it here: https://es6console.com/k6ehwu5p/

【讨论】:

  • 这绝对是解决这个问题的自然方法。为方便起见,我建议将这一切包装在一个可以用树调用以返回数组的函数中,这样调用者就不必自己创建空数组。
  • @samdouble 我们应该对您的代码进行哪些更改,以便能够从指定的 _id 开始并仅获得该节点下的结果?就像使用 _id 将一个参数传递给您的函数一样,并且仅从该 id 和树中的下面进行迭代。
  • @WilliamBird 我没试过,但是(对不起,我不知道如何在评论中格式化我的代码): function addNestedChildrenToArray(obj, resultArray, searchId, include=false) { const应该包括 = 包括 || obj._id === searchId; if (shouldInclude) { resultArray.push(obj._id); } obj._children.forEach(child => addNestedChildrenToArray(child, resultArray, searchId, shouldInclude)); } 常量结果数组 = []; addNestedChildrenToArray(data, resultArray, SEARCHID); // resultArray 现在包含结果 console.log(resultArray);
  • @samdouble 是的,它可以工作,谢谢,这是一个演示链接:es6console.com/kg28pqkw
【解决方案2】:

您可以展平一棵树,然后简单地获取 id。请参阅工作示例here

const tree = {
  "_id": "-1",
  "_name": "root",
  "_children": [
    // ...
  ]
}

function flattenTree(tree) {
  if (!tree) {
      return [];
  }

  if (tree._children) {
      const result = tree._children.reduce((prev, current) => prev.concat(flattenTree(current)), [tree]);
      return result;
  } else {
      return [tree];
  }
}

const plain = flattenTree(tree);
const ids = plain.map(value => value._id);

【讨论】:

    【解决方案3】:

    这是一个与@samdouble 的答案基本相同的解决方案;将当前节点的 ID 推送到结果数组,然后在节点的子节点上递归。

    结果数组必须在调用递归函数之前创建,所以为了方便,可以将其包裹在一个外部函数中;这使调用者不必创建一个空数组来传递给函数。

    interface TreeNode {
        _id: string;
        _name: string;
        _children: TreeNode[];
    }
    
    function getIds(data: TreeNode): string[] {
        const result: string[] = [];
        function helper(node: TreeNode): void {
            result.push(node._id);
            node._children.forEach(helper);
        }
        helper(data);
        return result;
    }
    

    Playground Link

    【讨论】:

      猜你喜欢
      • 2018-05-13
      • 1970-01-01
      • 2017-10-16
      • 1970-01-01
      • 1970-01-01
      • 2021-07-21
      • 2014-01-29
      相关资源
      最近更新 更多