为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

慕桂英546537 2023-07-06 16:33:48
我正在尝试将一个对象数组(数组中的每个对象都有一个路径和 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,            }          ]        }      ]    }]有人可以将我推向正确的方向吗?
查看完整描述

2 回答

?
MM们

TA贡献1886条经验 获得超2个赞

不要在回调中创建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.

}


查看完整回答
反对 回复 2023-07-06
?
长风秋雁

TA贡献1757条经验 获得超7个赞

该解决方案重组了您的原始代码。主要区别在于路径列表是相反的,因此我们从叶节点而不是根开始。


有一个显式检查来查看我们是否位于第一个索引(我们可以假设它是叶子)。或者,如果您愿意,您可以检查是否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);


查看完整回答
反对 回复 2023-07-06
  • 2 回答
  • 0 关注
  • 109 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信