简体   繁体   English

如何弄平(森林)树木?

[英]How do I flatten a (forest of) trees?

I have a forest of trees of arbitrary height, more or less like this: 我有一片任意高度的森林,大致是这样的:

let data = [
  { "id": 2, "name": "AAA", "parent_id": null, "short_name": "A" },
  {
    "id": 10, "name": "BBB", "parent_id": null, "short_name": "B", "children": [
      {
        "id": 3, "name": "CCC", "parent_id": 10, "short_name": "C", "children": [
          { "id": 6, "name": "DDD", "parent_id": 3, "short_name": "D" },
          { "id": 5, "name": "EEE", "parent_id": 3, "short_name": "E" }
        ]
      },
      {
        "id": 4, "name": "FFF", "parent_id": 10, "short_name": "F", "children": [
          { "id": 7, "name": "GGG", "parent_id": 4, "short_name": "G" },
          { "id": 8, "name": "HHH", "parent_id": 4, "short_name": "H" }
        ]
      }]
  }
];

And I'm trying to produce a representation of all the root-to-leaves paths, something like this 我正在尝试生成所有从根到叶的路径的表示,像这样

[
  [
    {
      "id": 2,
      "name": "AAA"
    }
  ],
  [
    {
      "id": 10,
      "name": "B"
    },
    {
      "id": 3,
      "name": "C"
    },
    {
      "id": 6,
      "name": "DDD"
    }
  ],
  [
    {
      "id": 10,
      "name": "B"
    },
    {
      "id": 3,
      "name": "C"
    },
    {
      "id": 5,
      "name": "EEE"
    }
  ],
  [
    {
      "id": 10,
      "name": "B"
    },
    {
      "id": 4,
      "name": "F"
    },
    {
      "id": 7,
      "name": "GGG"
    }
  ],
  [
    {
      "id": 10,
      "name": "B"
    },
    {
      "id": 4,
      "name": "F"
    },
    {
      "id": 8,
      "name": "HHH"
    }
  ]
]

So I wrote the following code: 所以我写了下面的代码:

function flattenTree(node, path = []) {
    if (node.children) {
        return node.children.map(child => flattenTree(child, [...path, child]));
  } else {
    let prefix = path.slice(0, path.length - 1).map(n => ({ id: n.id, name: n.short_name }));
    let last = path[path.length - 1];
    return [...prefix, { id: last.id, name: last.name } ];
  }
}

let paths = data.map(n => flattenTree(n, [n]));

but paths comes out with extra nesting, like this: 但是paths带有额外的嵌套,如下所示:

[
  [
    {
      "id": 2,
      "name": "AAA"
    }
  ],
  [
    [
      [
        {
          "id": 10,
          "name": "B"
        },
        {
          "id": 3,
          "name": "C"
        },
        {
          "id": 6,
          "name": "DDD"
        }
      ],
      [
        {
          "id": 10,
          "name": "B"
        },
        {
          "id": 3,
          "name": "C"
        },
        {
          "id": 5,
          "name": "EEE"
        }
      ]
    ],
    [
      [
        {
          "id": 10,
          "name": "B"
        },
        {
          "id": 4,
          "name": "F"
        },
        {
          "id": 7,
          "name": "GGG"
        }
      ],
      [
        {
          "id": 10,
          "name": "B"
        },
        {
          "id": 4,
          "name": "F"
        },
        {
          "id": 8,
          "name": "HHH"
        }
      ]
    ]
  ]
]

I lost count of the many ways in which I tried to fix this, but it does look like the algorithm should not produce the extra nesting -- or my eyes are just so crossed by now that I couldn't see my mistake if someone stuck their finger on it. 我没有办法尝试解决此问题的许多方法,但是看起来算法似乎不应该产生额外的嵌套-否则我的眼神已经非常交叉,以至于如果有人卡住,我将看不到我的错误他们的手指放在上面。

Can someone help? 有人可以帮忙吗? Feel free to peruse this JSFiddle https://jsfiddle.net/png7x9bh/66/ 随意阅读此JSFiddle https://jsfiddle.net/png7x9bh/66/

The extra nestings are created by map . 额外的嵌套由map创建。 map just wraps the results into an array and returns them, it doesn't care if it is called on child nodes or not. map只是将结果包装到一个数组中并返回它们,它不在乎是否在子节点上调用它。 Use reduce and just concat (or push , whatever suits your performance) the results into the first level array directly: 使用reduce ,只是concat (或push ,什么适合你的表现)的结果直接进入第一级阵列:

 let data = [{"id":2,"name":"AAA","parent_id":null,"short_name":"A"},{"id":10,"name":"BBB","parent_id":null,"short_name":"B","children":[{"id":3,"name":"CCC","parent_id":10,"short_name":"C","children":[{"id":6,"name":"DDD","parent_id":3,"short_name":"D"},{"id":5,"name":"EEE","parent_id":3,"short_name":"E"}]},{"id":4,"name":"FFF","parent_id":10,"short_name":"F","children":[{"id":7,"name":"GGG","parent_id":4,"short_name":"G"},{"id":8,"name":"HHH","parent_id":4,"short_name":"H"}]}]}]; function flattenTree(node, path = []) { let pathCopy = Array.from(path); pathCopy.push({id: node.id, name: node.name}); if(node.children) { return node.children.reduce((acc, child) => acc.concat(flattenTree(child, pathCopy)), []); } return [pathCopy]; } let result = data.reduce((result, node) => result.concat(flattenTree(node)), []); console.log(JSON.stringify(result, null, 3)); 

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

相关问题 我如何使用 javascript 挑战问题在森林中找到和格式化视觉上美观的树木图案 - How can I find and format visually aesthetically pleasant pattern of trees in a forest using javascript challenge question 如何将 object “展平”为 arrays 数组 - How do I “flatten” an object into an array of arrays 如何展平嵌套的 promise 依赖项? - How do I flatten a nested promise dependency? JavaScript:我如何展平这样的对象 - JavaScript: how do I flatten an object like this 如何遍历两棵相同的树并返回目标值? - How do I traverse two identical trees and return a target value? 使用Underscore,如何递归地展平对象数组? - With Underscore, how do I recursively flatten an array of objects? 如何仅将多维数组的一部分展平到一级? - How do I flatten part of a multidimensional array one level only? 如何使用无上下文语法从标记列表构造抽象语法树? - How do I construct abstract syntax trees from a list of tokens using a context-free grammar? 我如何将这个按标题分组的 json 展平,以便我可以以更易于理解的方式呈现这些数据? - How do I flatten this json grouped by headers so I can present this data in a more understandable way? javascript-如何将json数组展平为特定json属性的数组? - javascript - how do i flatten an array of json into an array of a particular json attributes?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM