4


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

baris usanmaz
  • 839
  • 1
  • 13
  • 31

4 Answers4

2

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>');
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
1

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(''));
Yuriy Yakym
  • 3,616
  • 17
  • 30
1

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.

Community
  • 1
  • 1
Andrew
  • 7,848
  • 1
  • 26
  • 24
0

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.

djechlin
  • 59,258
  • 35
  • 162
  • 290