简体   繁体   中英

Flat array to tree array using lodash.js


I am trying to convert a flat array to tree array since I will use the data in jsTree. Also I need to convert key names like "Name" to "text".
I want to use lodash.js but I am realy newbie on lodash. I searched about the solution but I could not find any to fit my case.
So can you help on this? My flat array data is below:

[
    {
        Id:1,
        Name: 'name1',
        Parent: 0
    },
    {
        Id:2,
        Name: 'name2',
        Parent: 1
    },
    {
        Id:3,
        Name: 'name3',
        Parent: 2
    },
    {
        Id:4,
        Name: 'name4',
        Parent: 1
    },
    {
        Id:5,
        Name: 'name5',
        Parent: 1
    },
    {
        Id:6,
        Name: 'name6',
        Parent: 5
    }
]

I would like to have tree data like:

{
    "id": 1, 
    "text" : "name1", 
    "children" : [
        { 
            "id": 2, 
            "text" : "name2", 
            "children" : [{
                "id": 3,
                "text": "name3"
            }] 
        },
        { 
            "id": 4, 
            "text" : "name4" 
        },
        { 
            "id": 5, 
            "text" : "name5",
            "children" : [{
                "id": 6,
                "text": "name6"
            }]  
        }
    ]
}

Thank you in advance

This is a proposal in plain Javascript for unsorted data.

 var data = [{ Id: 1, Name: 'name1', Parent: 0 }, { Id: 2, Name: 'name2', Parent: 1 }, { Id: 3, Name: 'name3', Parent: 2 }, { Id: 4, Name: 'name4', Parent: 1 }, { Id: 5, Name: 'name5', Parent: 1 }, { Id: 6, Name: 'name6', Parent: 5 }], tree = function (data, root) { var r; data.forEach(function (a) { this[a.Id] = { id: a.Id, text: a.Name, children: this[a.Id] && this[a.Id].children }; if (a.Parent === root) { r = this[a.Id]; } else { this[a.Parent] = this[a.Parent] || {}; this[a.Parent].children = this[a.Parent].children || []; this[a.Parent].children.push(this[a.Id]); } }, Object.create(null)); return r; }(data, 0); document.write('<pre>' + JSON.stringify(tree, 0, 4) + '</pre>'); 

If you are not sure if child cannot appear before parent, then you can use this code:

 var t = [{ Id: 1, Name: 'name1', Parent: 0 }, { Id: 2, Name: 'name2', Parent: 1 }, { Id: 3, Name: 'name3', Parent: 2 }, { Id: 4, Name: 'name4', Parent: 1 }, { Id: 5, Name: 'name5', Parent: 1 }, { Id: 6, Name: 'name6', Parent: 5 }]; var elements = []; t.forEach(function(element) { elements[element.Id] = { id: element.Id, text: element.Name, parent: element.Parent, children: [] } }); elements.forEach(function(element) { elements[element.parent] && elements[element.parent].children.push(element); delete element.parent; }) document.write(['<pre>', JSON.stringify(elements[1], 0, 3), '</pre>'].join('')); 

Something like

return _(data).map(function(val) { val.children = []; })
.map(function(val, key) {
    data[val.parent].children.push(val);
});

Abuses array indexing. You may need to build an auxiliary map from Id to index in the source data first.

This is just vanilla use of Array.map , so lodash not needed for this solution.

The function below builds a tree from a list of objects. It's not tight to any format.

function buildTree(flatList, idFieldName, parentKeyFieldName, fieldNameForChildren) {
    var rootElements = [];
    var lookup = {};

    flatList.forEach(function (flatItem) {
      var itemId = flatItem[idFieldName];
      lookup[itemId] = flatItem;
      flatItem[fieldNameForChildren] = [];
    });

    flatList.forEach(function (flatItem) {
      var parentKey = flatItem[parentKeyFieldName];
      if (parentKey != null) {
        var parentObject = lookup[flatItem[parentKeyFieldName]];
        if(parentObject){
          parentObject[fieldNameForChildren].push(flatItem);
        }else{
          rootElements.push(flatItem);
        }
      } else {
        rootElements.push(flatItem);
      }

    });

    return rootElements;
  }

Here is a fiddle using your example as input.

The original source comes from this answer .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM