Search code examples
javascriptarraystreehierarchy

Tree hierarchy using level and name information using javascript


I have following flat array of data, primarily with levels, and which is ordered. Based on the levels, I need to create a tree hierarchical array.

Following is the input:

[
    {
        "position": "CEO",
        "level": 1,
        "name": "Adam"
    },
    {
        "position": "President",
        "level": 2,
        "name": "Eva"
    },
    {
        "position": "Senior Vice President",
        "level": 3,
        "name": "Thein"
    },
    {
        "position": "Vice President",
        "level": 4,
        "name": "Rick"
    },
    {
        "position": "Vice President",
        "level": 4,
        "name": "Rosh"
    },
    {
        "position": "Vice President",
        "level": 4,
        "name": "Jenny"
    },
    {
        "position": "Vice President",
        "level": 4,
        "name": "Tim"
    },
    {
        "position": "Vice President",
        "level": 4,
        "name": "Gin"
    },
    {
        "position": "President",
        "level": 2,
        "name": "Nisham"
    },
    {
        "position": "Senior Vice President",
        "level": 3,
        "name": "Gil"
    },
    {
        "position": "Vice President",
        "level": 4,
        "name": "Lew"
    },
    {
        "position": "Vice President",
        "level": 4,
        "name": "Dan"
    },
    {
        "position": "Vice President",
        "level": 4,
        "name": "Henry"
    }
]

And the expected output is:

[
    {
        "position": "CEO",
        "level": 1,
        "name": "Adam",
        "children": [
            {
                "position": "President",
                "level": 2,
                "name": "Eva",
                "children": [
                    {
                        "position": "Senior Vice President",
                        "level": 3,
                        "name": "Thein",
                        "children":[
                            {
                                "position": "Vice President",
                                "level": 4,
                                "name": "Rick"
                            },
                            {
                                "position": "Vice President",
                                "level": 4,
                                "name": "Rosh"
                            },
                            {
                                "position": "Vice President",
                                "level": 4,
                                "name": "Jenny"
                            },
                            {
                                "position": "Vice President",
                                "level": 4,
                                "name": "Tim"
                            },
                            {
                                "position": "Vice President",
                                "level": 4,
                                "name": "Gin"
                            }
                        ]
                    }
                ]
            },
            {
                "position": "President",
                "level": 2,
                "name": "Nisham",
                "children":[
                    {
                        "position": "Senior Vice President",
                        "level": 3,
                        "name": "Gil",
                        "children":[
                            {
                                "position": "Vice President",
                                "level": 4,
                                "name": "Lew"
                            },
                            {
                                "position": "Vice President",
                                "level": 4,
                                "name": "Dan"
                            },
                            {
                                "position": "Vice President",
                                "level": 4,
                                "name": "Henry"
                            }
                        ]
                    }
                ]
            }

        ]
    }
]

I came across many stacks but all of them have a id and parent_id as a link. However, in this data, there is no id link between the array items.

I tried following code so far:

let root = {};
    let i = 0;
    data.forEach(el => {
        if (el["level"] == 1) {
            root = el;
            root.children = [];
        }
        if (el["level"] == 2) {
            root.children.push(el);
            root.children[i].children = [];
        }
        if (el["level"] == 3) {
            root.children[i].children.push(el);
            root.children[i].children[i].children = [];
        }
        if (el["level"] == 4) {
            root.children[i].children[i].children.push(el);
            root.children[i].children[i].children[i].children = [];
        }
        i++;
    });

It gives output for the first pass, but throws error later. I know it's not right and levels are hard coded, but that's the try so far.


Solution

  • You could use nearly an one-liner by using an levels array which keeps all levels of the last inserted objects.

    const
        data = [{ position: "CEO", level: 1, name: "Adam" }, { position: "President", level: 2, name: "Eva" }, { position: "Senior Vice President", level: 3, name: "Thein" }, { position: "Vice President", level: 4, name: "Rick" }, { position: "Vice President", level: 4, name: "Rosh" }, { position: "Vice President", level: 4, name: "Jenny" }, { position: "Vice President", level: 4, name: "Tim" }, { position: "Vice President", level: 4, name: "Gin" }, { position: "President", level: 2, name: "Nisham" }, { position: "Senior Vice President", level: 3, name: "Gil" }, { position: "Vice President", level: 4, name: "Lew" }, { position: "Vice President", level: 4, name: "Dan" }, { position: "Vice President", level: 4, name: "Henry" }],
        result = [],
        levels = [result];
    
    data.forEach(o => levels[o.level - 1].push({ ...o, children: levels[o.level] = []}));
    
    console.log(result);
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    An approach without unused children arrays.

    const
        data = [{ position: "CEO", level: 1, name: "Adam" }, { position: "President", level: 2, name: "Eva" }, { position: "Senior Vice President", level: 3, name: "Thein" }, { position: "Vice President", level: 4, name: "Rick" }, { position: "Vice President", level: 4, name: "Rosh" }, { position: "Vice President", level: 4, name: "Jenny" }, { position: "Vice President", level: 4, name: "Tim" }, { position: "Vice President", level: 4, name: "Gin" }, { position: "President", level: 2, name: "Nisham" }, { position: "Senior Vice President", level: 3, name: "Gil" }, { position: "Vice President", level: 4, name: "Lew" }, { position: "Vice President", level: 4, name: "Dan" }, { position: "Vice President", level: 4, name: "Henry" }],
        result = [],
        levels = [{ children: result }];
    
    data.forEach(function (o) {
        levels[o.level - 1].children = levels[o.level - 1].children || [];
        levels[o.level - 1].children.push(levels[o.level] = o);
    });
    
    console.log(result);
    .as-console-wrapper { max-height: 100% !important; top: 0; }