如何通过属性值从对象列表创建嵌套对象

时间:2019-01-07 21:52:35

标签: javascript

我面临着解析API并将响应组合到适当对象中的真正问题。我尝试了许多解决方案,但是它们都在很多方面都以失败告终。

如果有解决此类问题的答案-请提供链接。因为我发现了许多有关如何嵌套的问题,但没人能解决移位问题。

到目前为止,我收到的响应如下:

[
 {path: "1.0.0"},
 {path: "1.1"},
 {path: "13"},
 {path: "2"},
 {path: "1"},
 {path: "2.0.0.1"},
 {path: "3.0.1.1"}
]

我需要转变成这样:

 [  
   {  
      path:"1",
      subCategories:[  
         {  
            path:"1.0.0",
            subcategories:[]
         },
         {  
            path:"1.1",
            subcategories:[
                           {
                             path:"1.1.0",
                             subcategories: []
                           }
           ]
         },
      ]
   },
   {  
      path:"13",
      subcategories:[]
   },
   {  
      path:"2",
      subcategories:[  
         {  
            path:"2.0.0.1",
            subcategories:[]
         }
      ]
   },
   {  
      path:"3.0.1.1",
      subcategories:[]
   },
]

主要的复杂性是,在服务器端,我们可以隐藏任何类别,在这种情况下,子级应该代替父级。父母和孩子之间用点分隔。

如果您能帮助我,我将不胜感激。谢谢。

2 个答案:

答案 0 :(得分:0)

这仅支持2个级别,如果您需要支持任意数量的嵌套,则需要递归解决方案

var o = [{
    path: "1.0.0"
  },
  {
    path: "1.1"
  },
  {
    path: "13"
  },
  {
    path: "2"
  },
  {
    path: "1"
  },
  {
    path: "1.1.0"
  },
  {
    path: "2.0.0.1"
  },
  {
    path: "3.0.1.1"
  }
]

const result = o.reduce((memo, d) => {
    const key = d.path.split('.')[0]
    memo[key] ? memo[key].push(d) : memo[key] = [d]
    return memo
  }, [])
  .filter(Boolean)
  .map(items => items.map(d => d.path).sort())
  .map(items => items.reduce((memo, d) => {
    const dTransposed = {
      path: d,
      subCategories: []
    }

    if (!memo.path) {
      return dTransposed
    }
    const parent = memo.subCategories.find(c => d.startsWith(c.path))
    if (parent) {
      parent.subCategories.push(dTransposed)
    } else {
      memo.subCategories.push(dTransposed)
    }

    return memo
  }, {}))

console.log(result)

答案 1 :(得分:0)

您可以采用两步递归的方法来收集相同级别的项目,然后创建对象。

function getTree(array, prefix = []) {

    function getCommon(array) {
        return array.reduce((a, b) => {
            var l = 0;
            while (a[l] === b[l] && l in a) l++;
            return a.slice(0, l);
        });
    }

    var l = array.length && getCommon(array) + 1;

    return array
        .reduce((r, a) => {
            var left = a.slice(0, l),
                right = a.slice(l),
                temp = r.find(([b]) => left.join('.') === b.slice(0, l).join('.'));

            if (temp) {
                temp[1].push(right);
            } else {
                r.push([left, [right]]);
            }
            return r;
        }, [])
        .map(([p, sub]) => {
            var path = prefix.concat(p, sub.length === 1 ? sub[0] : []);
            return {
                path: path.join('.'),
                subcategories: sub.length === 1
                    ? []
                    : getTree(sub.filter(({ length }) => length), path)
            };
        });
}

var data = [{ path: "1.0.0" }, { path: "1.1" }, { path: "1.1.0" }, { path: "13" }, { path: "2" }, { path: "1" }, { path: "2.0.0.1" }, { path: "3.0.1.1" }],
    tree = getTree(data.map(({ path }) => path.split('.')));

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