JavaScript格式的对象数组到嵌套的子对象中

时间:2016-04-13 17:00:37

标签: javascript arrays sorting

我有一个带有parentId和排序值的对象数组,我想将它放入一个嵌套'children'的数组中并进行适当的排序。

例如,这是数据:

[{
    id: 1,
    sort: 2,
    parentId: null,
    name: 'A'
}, {
    id: 2,
    sort: 1,
    parentId: 1,
    name: 'A.1'
}, {
    id: 3
    sort: 2,
    parentId: 1,
    name: 'A.2'
}, {
    id: 4,
    sort: 1,
    parentId: null,
    name: 'B'
}]

我想改变它的方式如下:

[{
    id: 4,
    sort: 1,
    parentId: null,
    name: 'B',
    children: []
}, {
    id: 1,
    sort: 2,
    parentId: null,
    name: 'A',
    children: [{
        id: 2,
        sort: 1,
        parentId: 1,
        name: 'A.1'
    }, {
        id: 3
        sort: 2,
        parentId: 1,
        name: 'A.2'
    }]
}]

这是排序的(id 4位于顶部,因为sort为1)并且子项嵌套并相应地进行排序。

有关良好方法的任何建议吗?我可以递归循环来应用子项,但不知道如何维护对此的排序。

3 个答案:

答案 0 :(得分:3)

这是一个先排序并在此之后过滤的提案。

排序采用属性parentIdsort。这对于下一步是必要的,因为“过滤”需要一个排序的数组。

稍后使用Array#filter()过滤数组,此处thisArgs用于引用可能插入子项的节点。

修改:未分类(id / parentId)数据的更新。

var array = [{ id: 1, sort: 2, parentId: null, name: 'A' }, { id: 2, sort: 1, parentId: 1, name: 'A.1' }, { id: 3, sort: 2, parentId: 1, name: 'A.2' }, { id: 4, sort: 1, parentId: null, name: 'B' }],
    nested;

array.sort(function (a, b) {
    return (a.parentId || -1) - (b.parentId || -1) || a.sort - b.sort;
});

nested = array.filter(function (a) {
    a.children = this[a.id] && this[a.id].children;
    this[a.id] = a;
    if (a.parentId === null) {
        return true;
    }
    this[a.parentId] = this[a.parentId] || {};
    this[a.parentId].children = this[a.parentId].children || [];
    this[a.parentId].children.push(a);
}, Object.create(null));

document.write('<pre>' + JSON.stringify(nested, 0, 4) + '</pre>');

答案 1 :(得分:2)

我试了一下然后回来了,已经有其他答案了,但我还是张贴了它。

此方法修改原始数组:

&#13;
&#13;
var items = [{id: 1,sort: 2,parentId: null,name: 'A'}, {id: 2,sort: 1,parentId: 1,name: 'A.1'}, {id: 3,sort: 2,parentId: 1,name: 'A.2'}, {id: 4,sort: 1,parentId: null,name: 'B'}];


function generate_tree(arr){
  var references = {};
  arr.sort(function(a,b){
    // Save references to each item by id while sorting
    references[a.id] = a; references[b.id] = b;
    // Add a children property
    a.children = []; b.children = [];
    if(a.sort > b.sort) return 1;
    if(a.sort < b.sort) return -1;
    return 0;
  });

  for(var i=0; i<arr.length; i++){
    var item = arr[i];
    if(item.parentId !== null && references.hasOwnProperty(item.parentId)){
      references[item.parentId].children.push(arr.splice(i,1)[0]);
      i--; // Because the current index now contains the next item
    }
  }
  return arr;
}

document.body.innerHTML = "<pre>" + JSON.stringify(generate_tree(items), null, 4) + "</pre>";
&#13;
&#13;
&#13;

答案 2 :(得分:0)

  1. 我创建了一个新的数据结构,如下所示:

    {1:{     id:1,     排序:2,     parentId:null,     名称:'A'  },   2:{     id:4,     排序:1,     parentId:null,     名称:'B'  } }

  2. 需要注意的事项:新结构是一个对象,而不是一个数组,只包含其中最顶层的元素(parentId null

    1. 然后,对原始数组执行for,并指定new_obj[ orig_arr_curr_elem[parentId] ].children.push(orig_arr_curr_elem)

    2. 然后创建一个新数组,其中包含new_obj sort()(或children属性)中的元素

    3. 实现步骤1和2的代码(使用节点运行):

      var util = require('util');
      var old_arr = [{
          id: 1,
          sort: 2,
          parentId: null,
          name: 'A'
      }, {
          id: 2,
          sort: 1,
          parentId: 1,
          name: 'A.1'
      }, {
          id: 3,
          sort: 2,
          parentId: 1,
          name: 'A.2'
      }, {
          id: 4,
          sort: 1,
          parentId: null,
          name: 'B'
      }];
      
      var new_obj = {};
      for (var i = 0; i < old_arr.length; i++){
          if ( old_arr[i].parentId == null )
              new_obj[ old_arr[i].id ] = old_arr[i];
      }
      
      for (var i = 0; i < old_arr.length; i++){
          if ( old_arr[i].parentId == null ) continue;
          new_obj[ old_arr[i].parentId ].children = new_obj[ old_arr[i].parentId ].children || [];
          new_obj[ old_arr[i].parentId ].children.push( old_arr[i] );
      }
      
      console.log(util.inspect(new_obj, {showHidden: false, depth: null}));