Dreamer XD Dreamer XD - 28 days ago 7
Javascript Question

Dynamically convert array to tree-like structure

Can someone show me the most efficient way to convert an array to a tree-like structure?

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 must be like this:

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"
}]
}]


Thanks in advance

Answer

You could use a tree and build the nested array upon. This proposal needs a sorted list.

Basically it looks for the parent of a node and if a node has no parent, then a root node is found and inserted into the result array. If a parent is found, then the actual node is inserted into the items property of the parent.

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; }

Comments