从字符串列表创建树 - 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);