2

Given the following array of json objects:

var items = [
    {id:1, parentId:0, name:'item1'},
    {id:2, parentId:1, name:'item1.2'},
    {id:3, parentId:1, name:'item1.3'},
    {id:4, parentId:3, name:'item3.4'},
    {id:5, parentId:3, name:'item3.5'},
    ...more nesting, levels, etc.
];

And a base object like:

var myObj = function(id, parentId, name, children){
    this.id = id;
    this.parentId = parentId;
    this.name = name;
    this.children = children;
};

how do I use recursion to loop through this items array and build a new array like so:

var newArray = [
    new myObj(1, 0, 'item1', [
        new myObj(2, 1, 'item1.2', []),
        new myObj(3, 1, 'item1.3', [
            new myObj(4, 3, 'item3.4', []),
            new myObj(5, 3, 'item3.5', [])
        ])
    ]);
];

any help is greatly appreciated

edit: the parent/child relationship can be infinite. so i'm looking for a recursion function that would convert the first "items" array into the second "newarray"

Andre
  • 790
  • 1
  • 9
  • 25

2 Answers2

5

The title of your question is a bit misleading. You're trying to convert an array of items into a tree-like nested object.

Your use of the Object constructor is a bit redundant. Use quasi-literal notation ({foo:bar}) instead. Actually, you don't even need to create new objects, you can use the original ones.

First, convert the list to an object to facilitate referencing by id:

var map = {}
for (var i = 0; i < items.length; i++) {
   map[items[i].id] = items[i];
}

Now, iterate through the items and add children array:

var newArray = [];
for (id in map) {
    var item = map[id];
    var parent = map[item.parentId];
    if (parent) {
        parent.children = parent.children || [];
        parent.children.push(item); // add reference to item
    } else { // root
        newArray.push(item);
    }
}

Note that this modifies the original items array, and newArray holds pointers to its entries. If you don't want that, create a copy of items first.

Community
  • 1
  • 1
user123444555621
  • 148,182
  • 27
  • 114
  • 126
  • This works as well as the answer I accepted. My limited js knowledge just made it harder to figure out how to do with your code what @marspzb had demonstrated in the example jfiddle. but thanks for your answer as well – Andre Apr 01 '12 at 16:09
  • typo? maybe `for (var id in map) {` instead of `for (id in map) {` ? – pupadupa Jun 28 '13 at 22:42
3

I don't know if this helps, but in this fiddle there's an iterative solution that creates that newArray.
Using a json obj as an array and then adding the children as you iterate over the items array.

marspzb
  • 364
  • 1
  • 8
  • This solution doesn't use recursion so it doesn't always work. Depending on the order of the items it could break. – Paul Jan 12 '15 at 22:34