tdk
tdk

Reputation: 151

Creating tree hierarchy from array of objects

First of all, I just want to mention that I really tried to find solution for my problem, but I couldn't find anything that would fit me. Thing is, I have such array:

const arr = [
  {
    leafName: 'name1',
    nodes: [1,2,3,4]
  },
  {
    leafName: 'name2',
    nodes: [1,2,3,4]
  },
  {
    leafName: 'name3',
    nodes: [1,2,4,5]
  },
  {
    leafName: 'name4',
    nodes: [6]
  }
];

and what I expect to have is this:

const expectedTree = {
  name: 'some root name',
  children: [
    {
      name: 1,
      children: [
        {
          name: 2,
          children: [
            {
              name: 3,
              children: [
                {
                  name: 4,
                  children: [
                    {
                      name: 'name1'
                    },
                    {
                      name: 'name2'
                    }
                  ]
                }
              ]
            },
            {
              name: 4,
              children: [
                {
                  name: 5,
                  children: [
                    {
                      name: 'name3'
                    }
                  ]
                }
              ]
            }
          ]
        }
      ]
    },
    {
      name: 6,
      children: [
        {
          name: 'name4'
        }
      ]
    }
  ]
};

as you can see leafName should be last node in tree branch. Also if there is partial match from root node to some other node, new child should be added from node which matches last. For example let's take arr[1].nodes and arr[2].nodes first two members match, so that means that they should be in same branch just 4 and 5 from arr[2].nodes split to separate branch(as children for { name: 2, children: [should go here] }). I really hope you get the idea and I also hope that someone will help me with this. Because I am stuck with this for two days now and I couldn't figure out 'clean' solution for this myself.

Any comments would be very appreciated. ;)

Upvotes: 1

Views: 231

Answers (1)

Nina Scholz
Nina Scholz

Reputation: 386522

You could loop the array and the nodes and reduce nodes by looking at same name for each level. If a node does not exist, create a new one and return the children of the node.

var array = [{ leafName: 'name1', nodes: [1, 2, 3, 4] }, { leafName: 'name2', nodes: [1, 2, 3, 4] }, { leafName: 'name3', nodes: [1, 2, 4, 5] }, { leafName: 'name4', nodes: [6] }],
    result = [];

array.forEach(({ leafName, nodes }) => {
    nodes
        .reduce((level, name) => {
            var temp = level.find(o => o.name === name);
            if (!temp) {
                level.push(temp = { name });
            }
            return temp.children = temp.children || [];
        }, result)
        .push({ name: leafName });
});

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

Upvotes: 2

Related Questions