1

I've been trying to solve a problem with arrays and objects for some time now - but I still can't find the right solution.

This is my starting position:

list = [
{
    lastItemData: {data:"root"},
    path: ["Root"]
},
{
    lastItemData: {data:"level2_Summer"},
    path: ["Root", "Level2_Summer"]
},
{
    lastItemData: {data:"Level3_Monday"},
    path: ["Root", "Level2_Winter", "Level3_Monday"]
},
{
    lastItemData: {data:"Level4_Morning"},
    path: ["Root", "Level2_Spring", "Level3_Tuesday", "Level4_Morning"]
},
{
    lastItemData: {data:"Level3_Sunday"},
    path: ["Root", "Level2_Autumn", "Level3_Sunday"]
}]

and this is what i need:

result = [
{
    text: "Root",
    lastItemData: {data:"root"},
    Items:[
        {
            text:"Level2_Summer",
            lastItemData: {data:"level2_Summer"},
            Items: []
        },
        {
            text:"Level2_Winter",
            Items:[
                {
                    text: "Level3_Monday",
                    lastItemData: {data:"Level3_Monday"},
                    Items: []
                }
            ]
        },
        {
            text:"Level2_Spring",
            Items:[
                {
                    text: "Level3_Tuesday"
                    Items: [
                        {
                            text:"Level4_Morning"
                            Items:[],
                            lastItemData: {data:"Level4_Morning"},
                        }
                    ]
                }
            ]
        },
        {
            text:"Level2_Autumn",
            Items:[
                {
                    text: "Level3_Sunday"
                }
            ]
        },
    ]
}]

I'v try something like this (code is based on user jonas answer from my deleted post)

const property = list.reduce((previous, current, index) => {


            let acc = {}; //the accumulator that will go deep into the object
            const result = acc; //our result will be the top level object

            debugger;

            //Now we iterate over our array
            for (var i = 0; i < current.stringPath.length; i++) {
                debugger;
                //add the string part
                acc["level" + (i + 1)] = current.stringPath[i];
                //Add the children array
                acc["Items"] = [{}];
                //And go into the object
                acc = acc["Items"][0];
            }

            console.log(result)

            previous.push(result);

            return previous;

        }, []);

        console.log("property", property);

But unfortunately the result does not correspond to the desired structure. Can anyone help me?

4
  • 1
    Why would you delete a post about the same topic that already has an answer? This is rude towards the person that spent time answering you. Commented Jan 2, 2018 at 7:37
  • 1
    @Tomalak: Indeed, if it was the OP that deleted it rather than the community. Isabelle - If appropriate, you can find the previous post by going to your profile > Activity > Questions, scrolling to the bottom, and clicking deleted recent questions (I think that's the right link), undelete it, and then either ask for clarification on existing answers to it (and delete this question) or, if this is a new question, link to that question in the text. Commented Jan 2, 2018 at 7:44
  • That does not show up for me, unfortunately. Commented Jan 2, 2018 at 7:55
  • I asked the question last time - but it was not very clear, the formatting of the code was wrong and in general unclear. One user asked me to delete the question and ask it again. What i did. But there was no solution to the question. Otherwise, I wouldn't ask the same question twice. Commented Jan 2, 2018 at 8:01

1 Answer 1

1

This is a far more complex problem as it looks like, because you have to build a nested structure with a given name (text property) and you need to check if that name exist or not. If not create a new object and push it to the parent array.

This solution features a hash table where all nested hashes for each level are collected and maintained. The result is an array with the wanted tree.

It works as follows:

First have a look into the root of the hash table and check if the path value exists. If not, create a new node with the information and push it to the hash collector, denoted with _. Then return that node and go on with iteration of the given path.

At the and of the path use lastItemData for the wanted object.

var list = [{ lastItemData: { data: "root" }, path: ["Root"] }, { lastItemData: { data: "level2_Summer" }, path: ["Root", "Level2_Summer"] }, { lastItemData: { data: "Level3_Monday" }, path: ["Root", "Level2_Winter", "Level3_Monday"] }, { lastItemData: { data: "Level4_Morning" }, path: ["Root", "Level2_Spring", "Level3_Tuesday", "Level4_Morning"] }, { lastItemData: { data: "Level3_Sunday" }, path: ["Root", "Level2_Autumn", "Level3_Sunday"] }],
    tree = function (array) {
        var result = [],
            hash = { _: { Items: result } };

        array.forEach(function (object) {
            object.path.reduce(function (o, p) {
                if (!o[p]) {
                    o[p] = { _: { text: p, Items: [] } };
                    o._.Items.push(o[p]._);
                }
                return o[p];
            }, hash)._.lastItemData = object.lastItemData;
        });
        return result;
    }(list);

console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, Nina! I would never have found such a solution. I'm gonna try this right now.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.