从字符串列表创建树 - javascript
Create a tree from a list of strings - javascript
我有一个对象数组,我想创建一个视图树。但是我在创建时遇到了问题。我的名字 Test1/Test2 和 Test1/Test2/Test3 (id 147) 在最后一棵树中遗漏了。
我的片段:
let arr = [{id: 145, name: "Test1/Test2", public: false},
{id: 146, name: "Test1/Test2/Test3", public: false},
{id: 147, name: "Test1/Test2/Test3", public: false},
{id: 148, name: "Test1/Test2/Test4", public: false}];
let result = [];
let level = { result };
arr.forEach((path) => {
path.name.split("/").reduce((r, name, i, a) => {
if (!r[name]) {
r[name] = { result: [], id: path.id };
r.result.push({ name, children: r[name].result });
}
return r[name];
}, level);
});
console.log(result)
预期结果:
[
{
name: "Test1",
children: [
{
name: "Test2",
children: [],
id: 145
},
{
name: "Test2",
children: [
{
name: "Test3",
children: [],
id: 146
},
{
name: "Test3",
children: [],
id: 147
},
{
name: "Test4",
children: [],
id: 148
},
],
},
],
},
];
如果我理解得很好,树中的叶子数应该等于输入数组中的条目数。所以一片叶子永远得不到任何children。这就是为什么你给“Test1”两个 children,即使所有路径都有“Test2”作为下一部分:一个 child 用于叶子,另一个用作内部节点。
因此,叶子并不真正需要 children
属性,因为 children
数组将始终为空。
很明显,路径的最后一个元素需要进行一些不同的处理。该部分应始终导致在树中创建新节点。其他部分可以重用一个 (non-leaf) 节点,如果有的话。
这会导致您的代码发生以下变化:
let arr = [
{id: 145, name: "Test1/Test2", public: false},
{id: 146, name: "Test1/Test2/Test3", public: false},
{id: 147, name: "Test1/Test2/Test3", public: false},
{id: 148, name: "Test1/Test2/Test4", public: false}
];
let result = [];
let level = { result };
arr.forEach(({name, id}) => { // destructure
let parts = name.split("/");
name = parts.pop(); // don't pass the last part through reducer
parts.reduce((r, name, i) => {
if (!r[name]) {
r[name] = { result: [] };
r.result.push({ name, children: r[name].result });
}
return r[name];
}, level).result.push({ name, id }); // add last part here
});
console.log(result);
我有一个对象数组,我想创建一个视图树。但是我在创建时遇到了问题。我的名字 Test1/Test2 和 Test1/Test2/Test3 (id 147) 在最后一棵树中遗漏了。
我的片段:
let arr = [{id: 145, name: "Test1/Test2", public: false},
{id: 146, name: "Test1/Test2/Test3", public: false},
{id: 147, name: "Test1/Test2/Test3", public: false},
{id: 148, name: "Test1/Test2/Test4", public: false}];
let result = [];
let level = { result };
arr.forEach((path) => {
path.name.split("/").reduce((r, name, i, a) => {
if (!r[name]) {
r[name] = { result: [], id: path.id };
r.result.push({ name, children: r[name].result });
}
return r[name];
}, level);
});
console.log(result)
预期结果:
[
{
name: "Test1",
children: [
{
name: "Test2",
children: [],
id: 145
},
{
name: "Test2",
children: [
{
name: "Test3",
children: [],
id: 146
},
{
name: "Test3",
children: [],
id: 147
},
{
name: "Test4",
children: [],
id: 148
},
],
},
],
},
];
如果我理解得很好,树中的叶子数应该等于输入数组中的条目数。所以一片叶子永远得不到任何children。这就是为什么你给“Test1”两个 children,即使所有路径都有“Test2”作为下一部分:一个 child 用于叶子,另一个用作内部节点。
因此,叶子并不真正需要 children
属性,因为 children
数组将始终为空。
很明显,路径的最后一个元素需要进行一些不同的处理。该部分应始终导致在树中创建新节点。其他部分可以重用一个 (non-leaf) 节点,如果有的话。
这会导致您的代码发生以下变化:
let arr = [
{id: 145, name: "Test1/Test2", public: false},
{id: 146, name: "Test1/Test2/Test3", public: false},
{id: 147, name: "Test1/Test2/Test3", public: false},
{id: 148, name: "Test1/Test2/Test4", public: false}
];
let result = [];
let level = { result };
arr.forEach(({name, id}) => { // destructure
let parts = name.split("/");
name = parts.pop(); // don't pass the last part through reducer
parts.reduce((r, name, i) => {
if (!r[name]) {
r[name] = { result: [] };
r.result.push({ name, children: r[name].result });
}
return r[name];
}, level).result.push({ name, id }); // add last part here
});
console.log(result);