从具有平坦路径的对象数组生成嵌套对象

我正在尝试将一个对象数组(数组中的每个对象都有一个路径和 id)转换为表示该路径的树。例如,对于给定的输入,输出如下 [{path: 'foo/bar/baz', id: 1}]


[

    {

      "path": "foo",

      "children": [

        {

          "path": "bar",

          "children": [

            {

              "path": "baz",

              "children": [],

            }

          ]

        }

      ]

    }

]

到目前为止,我有以下代码:



const pathObjs = [

    { id: 1, path: 'foo/bar/baz' },

  ];


const result = [];

const level = { result };


for (p of pathObjs) {

  p.path.split('/').reduce((r, path) => {

    if (!r[path]) {

      r[path] = { result: [] };


      const p = { path, children: r[path].result };


      r.result.push(p);

    }


    return r[path];

  }, level);

}


我无法弄清楚如何id在正确的级别分配每个路径的 ,以便最终结果如下所示:


[

    {

      "path": "foo",

      "children": [

        {

          "path": "bar",

          "children": [

            {

              "path": "baz",

              "children": [],

              // how to add this guy here!

              "id": 1,

            }

          ]

        }

      ]

    }

]

有人可以将我推向正确的方向吗?


慕桂英546537
浏览 111回答 2
2回答

MM们

不要在回调中创建const p局部变量reduce,而是使用完成后可访问的变量reduce,以便您可以访问最后分配的对象以添加附加属性(或多个属性)。所以改变:      const p = { path, children: r[path].result };      r.result.push(p);到:      last = { path, children: r[path].result };      r.result.push(last);并last在块的作用域中定义为局部变量for。完成后reduce,您可以使用Object.assign来改变“叶子”对象,添加额外的属性:  Object.assign(last, rest); // rest is whatever needs to be added.所以你的代码可以修改如下:const result = [];const level = { result };for (p of pathObjs) {  let last; // This will be the latest added object  let { path, ...rest } = p; // Extract the path and the other properties  path.split('/').reduce((r, path, i, {length}) => {    if (!r[path]) {      r[path] = { result: [] };      last = { path, children: r[path].result };      r.result.push(last);    }    return r[path];  }, level);  Object.assign(last, rest); // Extend with the extra properties.}

长风秋雁

该解决方案重组了您的原始代码。主要区别在于路径列表是相反的,因此我们从叶节点而不是根开始。有一个显式检查来查看我们是否位于第一个索引(我们可以假设它是叶子)。或者,如果您愿意,您可以检查是否result已定义,并依赖它而不是索引。const pathObjects = [{ id: 1, path: "foo/bar/baz" }];const result = [];for (let { id, path } of pathObjects) {  const obj = path    .split("/")    .reverse()    .reduce((result, path, index) => {      const node = {        path,        children: result ? [result] : []      };      if (index === 0) {        node.id = id;      }      return node;    }, null);  result.push(obj);}console.log(result);
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript