autofunk
autofunk

Reputation: 63

Create a hierarchical object from a flat list parent-child

I am trying to understand the best approach in JS to create an object to pass to a tree view component. I'm struggling to understand where to begin with regards to the approach. I have tried doing various things such as splitting the parent child relationship number into an array and then iterating over them, pushing them into a new object, but I still don't know how to keep the relationships. Do i need recursion?

Given the following list of parent child relationships, and associated depth level

1 , depth 1
1.1, depth 2
1.1.1, depth 3
1.1.2, depth 3
1.2.1, depth 3
1.2.2, depth 3
1.2.3, depth 3
1.2.3.4, depth 4

and the output tree below

1
-1
--1
--2
-2
--1
---1
...

Resulting object should looking like

[
  {
    "1": {
      "depth": "1",
      "child": {
        "1.1": {
          "depth": "2",
          "child": {
            "1.1.1": {
              "depth": "3",
              "child": null
            }
          }
        }
      }
    },
    "2": {
      "level": "2",
      "depth": "1",
      "child": {
        "2.1": {
          "depth": "2",
          "child": {
            "2.1.1": {
              "depth": "3",
              "child": null
            }
          }
        }
      }
    }
  }
]

What would be the best approach in JS to iterate through the list and generate a tree digram, or atleast the object that a tree diagram component could consume?

Upvotes: 1

Views: 611

Answers (1)

Nina Scholz
Nina Scholz

Reputation: 386570

By having an array of sorted items and a level information, you could use an helper array fro keeping track of the last inserted items at a givel level and use this storage to get nested items to the right place.

This approach does not rely on the given title, only on the order of the items and level.

var data = [{ title: '1', level: 1 }, { title: '1.1', level: 2 }, { title: '1.1.1', level: 3 }, { title: '1.1.2', level: 3 }, { title: '1.2.1', level: 3 }, { title: '1.2.2', level: 3 }, { title: '1.2.3', level: 3 }, { title: '1.2.3.4', level: 4 }],
    result = [],
    levels = [result];

data.forEach(({ title, level }) =>
    levels[level - 1].push({ title, children: levels[level] = [] })
);

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

The wanted one. No level used.

var data = [{ title: '1', level: 1 }, { title: '1.1', level: 2 }, { title: '1.1.1', level: 3 }, { title: '1.1.2', level: 3 }, { title: '1.2.1', level: 3 }, { title: '1.2.2', level: 3 }, { title: '1.2.3', level: 3 }, { title: '1.2.3.4', level: 4 }],
    result = {};

data.forEach(({ title, level }) =>
    title
        .split('.')
        .reduce((o, _, i, values) => {
            var key = values.slice(0, i + 1).join('.');
            o.child = o.child || {};
            return o.child[key] = o.child[key] || { depth: i + 1 };
        }, { child: result })
);

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

Upvotes: 2

Related Questions