动态将数组转换为类似树形的结构。

5
有人能向我展示将数组转换为树形结构的最有效方法吗?
var array= [
        {id: "1",     name: "header1"},
        {id: "2",     name: "header2"},
        {id: "1.1",   name: "subheader1.1"},
        {id: "1.2",   name: "subheader1.2"},
        {id: "2.1",   name: "subheader2.1"},
        {id: "2.2",   name: "subheader2.2"},
        {id: "1.1.1", name: "subheader1detail1"},
        {id: "2.1.1", name: "subheader2detail2"}
];

结果数组必须如下所示:

var array = [{
    id: "1",
    name: "header1",
    items: [{
        id: "1.1",
        name: "subheader1.1",
        items: [{
            id: "1.1.1",
            name: "subheader1detail1",
        }]
    }, {
        id: "1.2",
        name: "subheader1.2"
    }]
}, {
    id: "2",
    name: "header2",
    items: [{
        id: "2.1",
        name: "subheader2.1",
        items: [{
            id: "2.1.1",
            name: "subheader2detail2",
        }]
    }, {
        id: "2.2",
        name: "subheader2.2"
    }]
}]

感谢您的提前帮助。

有子程序吗?潜水艇?冲锋枪?代课老师?减法?副标题?? - zer00ne
请以一种不需要上下文也能理解的方式提出问题,或者提供上下文。 - Gokhan Kurt
zer00ne和Gokhan子内容 - Dreamer XD
需求应该从结果数组中清晰明确。源数组中的项目应该被转换成类似树形结构的形式:{ id: 1, items: [ 1.1, 1.2 ] }, { id: 2, items: [ 2.1, 2.2 ] }, ...。但这不是一个“让我来完成我的工作”的地方。你尝试过什么?你有什么问题/疑问? - Andreas
@Andreas 不知道该如何开始。 - Dreamer XD
3个回答

5
你可以使用树来构建嵌套数组。这个方案需要一个排序的列表。
基本上,它寻找一个节点的父节点,如果一个节点没有父节点,那么就找到了一个根节点,并将其插入结果数组中。如果找到了父节点,则将实际节点插入父节点的“items”属性中。

var array = [{ id: "1", name: "header1" }, { id: "2", name: "header2" }, { id: "1.1", name: "subheader1.1" }, { id: "1.2", name: "subheader1.2" }, { id: "2.1", name: "subheader2.1" }, { id: "2.2", name: "subheader2.2" }, { id: "1.1.1", name: "subheader1detail1" }, { id: "2.1.1", name: "subheader2detail2" }],
    result = [];

array.forEach(function (a) {
    var parent = a.id.split('.').slice(0, -1).join('.');

    this[a.id] = { id: a.id, name: a.name };
    if (parent) {
        this[parent] = this[parent] || {};
        this[parent].items = this[parent].items || [];
        this[parent].items.push(this[a.id]);
    } else {
        result.push(this[a.id]);
    }
}, {});

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


3
你让事情看起来如此简单!只是一个小建议,你应该对任何未排序的数组进行排序。其余部分真是太棒了!!! - Rajesh
@Nina非常有帮助,请为我评论逻辑,以便我理解。谢谢:)) - Dreamer XD

0
你可以试试这样做:
我已经添加了注释来解释逻辑。

var array= [
  {id: "1",     name: "header1"},
  {id: "2",     name: "header2"},
  {id: "1.1",   name: "subheader1.1"},
  {id: "1.2",   name: "subheader1.2"},
  {id: "2.1",   name: "subheader2.1"},
  {id: "2.2",   name: "subheader2.2"},
  {id: "1.1.1", name: "subheader1detail1"},
  {id: "2.1.1", name: "subheader2detail2"},
];

var result = {};

// Sort in case values are not in order. 
// This is to ensure parent is rendered before child
array.sort(function(a, b) {
  return a.id > b.id ? 1 : a.id - b.id ? -1 : 0
})
// Loop over sorted array to parse
.forEach(function(el) {
  // Check if element does not exists to prevent duplicate
  if (!result[el.id]) {
    // if parent, push it
    if (el.id.indexOf('.') === -1)
      result[el.id] = el;
    // If child, compute depth and search object to push to
    else {
      var ids = el.id.split('.');
      var _id = '';
      // temp variable to hold position to push
      var r = result[ids[0]];
      for (var i = 1; i < ids.length; i++) {
        // Compute the object id
        _id = (_id ? _id + '.' : _id) + ids[i - 1];
        // initialize items
        r.items = r.items || [];
        // search in items to get object if exist
        var o = r.items.find(x => x.id === _id);
        // if object exists, assign it to temp variable
        // If not, push to parent
        if (o) r = o;
      }
      if (r) {
        r.items = r.items || [];
        r.items.push(el);
      }
    }
  }
})

console.log(result)

注意:我已经更改了结构,现在用一个对象来代替数组。

0
在这里研究了一下这个问题 - 使用Array.prototype.reduce和一个本地的哈希表来共享解决方案 - 同时对结果进行排序。干杯!

var array=[{id:"2",name:"header2"},{id:"1",name:"header1"},{id:"1.1",name:"subheader1.1"},{id:"1.2",name:"subheader1.2"},{id:"2.2",name:"subheader2.2"},{id:"2.1",name:"subheader2.1"},{id:"1.1.1",name:"subheader1detail1"},{id:"2.1.1",name:"subheader2detail2"}];

var result = array.sort(function(a,b) {
  return a.id - b.id;
}).reduce(function(hash) {
  return function(prev, curr) {
    var keys = curr.id.split('.');
    hash[curr.id] = hash[curr.id] || {};
    hash[curr.id] = {id: curr.id,name: curr.name};
    if (keys && keys.length > 1) {
      keys.pop();
      var key = keys.join('.');
      hash[key].items = hash[key].items || [];
      hash[key].items.push(hash[curr.id]);
    } else {
      prev.push(hash[curr.id]);
    }
    return prev;
  };
}(Object.create(null)), []);

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接