[英]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.