【问题标题】:Building tree array of objects from flat array of objects [duplicate]从平面对象数组构建对象树数组[重复]
【发布时间】:2017-10-20 10:48:57
【问题描述】:

我想从平面数组构建一个树数组:

这是平面数组:

nodes = [
    {id: 1, pid: 0, name: "kpittu"},
    {id: 2, pid: 0, name: "news"},
    {id: 3, pid: 0, name: "menu"},
    {id: 4, pid: 3, name: "node"},
    {id: 5, pid: 4, name: "subnode"},
    {id: 6, pid: 1, name: "cace"}
];

注意:id = 节点id; pid = 父节点 ID。

我想把它变成这个数组:

nodes = [{
    id: 1,
    name: 'kpittu',
    childs: [{
        id: 6,
        name: 'cace'
    }]
}, {
    id: 2,
    name: 'news'
}, {
    id: 3,
    name: 'menu',
    childs: [{
        id: 4,
        name: 'node',
        childs: [{
            id: 5,
            name: 'subnode'
        }]
    }]
}];

我尝试使用递归函数来实现预期结果,但我正在寻找更好的方法。感谢您的回复。

【问题讨论】:

  • 请同时添加您的功能。
  • 建议,如果你自己不弄清楚,你将无法学习或练习你的递归知识,而是回答这个问题的人

标签: javascript angular typescript


【解决方案1】:

您可以使用哈希表并将每个循环中的idpid 作为连接节点。

此提议也适用于未排序的数据。

var nodes = [{ id: 6, pid: 1, name: "cace" }, { id: 1, pid: 0, name: "kpittu" }, { id: 2, pid: 0, name: "news" }, { id: 3, pid: 0, name: "menu" }, { id: 4, pid: 3, name: "node" }, { id: 5, pid: 4, name: "subnode" }],
    tree = function (data, root) {
        var r = [], o = {};
        data.forEach(function (a) {
            if (o[a.id] && o[a.id].children) {
                a.children = o[a.id] && o[a.id].children;
            }
            o[a.id] = a;
            if (a.pid === root) {
                r.push(a);
            } else {
                o[a.pid] = o[a.pid] || {};
                o[a.pid].children = o[a.pid].children || [];
                o[a.pid].children.push(a);
            }
        });
        return r;
    }(nodes, 0);

console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

    【解决方案2】:

    你也可以使用 ES6 中引入的 Map 对象。

    let nodes = [
      { id: 1, pid: 0, name: "kpittu" },
      { id: 2, pid: 0, name: "news" },
      { id: 3, pid: 0, name: "menu" },
      { id: 4, pid: 3, name: "node" },
      { id: 5, pid: 4, name: "subnode" },
      { id: 6, pid: 1, name: "cace" }
    ];
    
    function toTree(arr) {
      let arrMap = new Map(arr.map(item => [item.id, item]));
      let tree = [];
    
      for (let i = 0; i < arr.length; i++) {
        let item = arr[i];
    
        if (item.pid) {
          let parentItem = arrMap.get(item.pid);
    
          if (parentItem) {
            let { children } = parentItem;
    
            if (children) {
              parentItem.children.push(item);
            } else {
              parentItem.children = [item];
            }
          }
        } else {
          tree.push(item);
        }
      }
    
      return tree;
    }
    
    let tree = toTree(nodes);
    
    console.log(tree);
    
    

    【讨论】:

      【解决方案3】:

      使用 Array#reduce 和辅助对象进行迭代:

      var nodes = [
        {id: 1, pid: 0, name: "kpittu"},
        {id: 2, pid: 0, name: "news"},
        {id: 3, pid: 0, name: "menu"},
        {id: 4, pid: 3, name: "node"},
        {id: 5, pid: 4, name: "subnode"},
        {id: 6, pid: 1, name: "cace"}
      ];
      
      const helper = nodes.reduce((h, o) => (h[o.id] = Object.assign({}, o), h), Object.create(null));
      
      const tree = nodes.reduce((t, node) => {
        const current = helper[node.id];
        
        if(current.pid === 0) { // if it doesn't have a parent push to root
          t.push(current);
        } else {
          helper[node.pid].children || (helper[node.pid].children = []) // add the children array to the parent, if it doesn't exist
          helper[node.pid].children.push(current); // push the current item to the parent children array
        }
        
        return t;
      }, []);
      
      console.log(tree);

      【讨论】:

        猜你喜欢
        • 2015-12-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-08
        • 2019-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多