Search code examples
javascriptarraysjsontreehierarchy

How to convert a raw data into hierarchical structure


I have raw data from database table which is not having direct relation wit one another. But I'm having a set of keys, that gives us the order of the hierarchy in our data.

Tried something like this. But couldn't get desired output.

Input Data

const data = {
  item1: {
    chancellor: "my-chancellor-1",
    viceChancellor: "my-vice-chancellor-1",
    headProfessor: "my-head-professor-1",
    student: "student-1",
    intern: null,
  },
  item2: {
    chancellor: "my-chancellor-1",
    viceChancellor: "my-vice-chancellor-1",
    headProfessor: "my-head-professor-1",
    student: null,
    intern: null,
  },
  item3: {
    chancellor: "my-chancellor-1",
    viceChancellor: "my-vice-chancellor-1",
    headProfessor: "my-head-professor-1",
    student: "student-2",
    intern: null,
  },
  item4: {
    chancellor: "my-chancellor-1",
    viceChancellor: "my-vice-chancellor-1",
    headProfessor: "my-head-professor-1",
    student: "student-3",
    intern: "intern-1",
  },
}

As i said, we have keys to identify the hierarchy. Suppose the keys are

const keyArray = ["chancellor", "viceChancellor", "headProfessor", "student", "intern"]

How can we get an output in a hierarchy structure?

Output

[
  {
    keyName: "chancellor",
    name: "my-chancellor-1",
    children: [
      {
        keyName: "viceChancellor",
        name: "my-vice-chancellor-1",
        children: [
          {
            keyName: "headProfessor",
            name: "my-head-professor-1",
            children: [
              {
                keyName: "student",
                name: "student-1",
              },
              {
                keyName: "student",
                name: "student-2",
              },
              {
                keyName: "student",
                name: "student-3",
                children: [
                  {
                    keyName: "intern",
                    name: "intern-1",
                  },
                ],
              },
            ],
          },
        ],
      },
    ],
  },
];

Solution

  • Please find the solution program, it is bit verbose, since I didn't use any ES6 features. but it still works as per expectation logically.

    const data = {
      item1: {
        chancellor: "my-chancellor-1",
        viceChancellor: "my-vice-chancellor-1",
        headProfessor: "my-head-professor-1",
        student: "student-1",
        intern: null,
      },
      item2: {
        chancellor: "my-chancellor-1",
        viceChancellor: "my-vice-chancellor-1",
        headProfessor: "my-head-professor-1",
        student: null,
        intern: null,
      },
      item3: {
        chancellor: "my-chancellor-1",
        viceChancellor: "my-vice-chancellor-1",
        headProfessor: "my-head-professor-1",
        student: "student-2",
        intern: null,
      },
      item4: {
        chancellor: "my-chancellor-1",
        viceChancellor: "my-vice-chancellor-1",
        headProfessor: "my-head-professor-1",
        student: "student-3",
        intern: "intern-1",
      },
    };
    const keyArray = ["chancellor", "viceChancellor", "headProfessor", "student", "intern"]
    
    let output = [];
    let parent = null;
    
    Object.keys(data).forEach(dk => {
      parent = output.find(el => el.name == data[dk][keyArray[0]]);
      keyArray.forEach(kele => {
        if (!data[dk][kele]) {
          return;
        }
        let child = {
          "keyName": kele,
          "name": data[dk][kele]
        };
        if (!parent) {
          output.push(child);
          parent = child;
        } else {
          if (!parent.children)
            parent.children = [];
          let alreadyPresentChild = parent.children.find(chl => chl.name == child.name);
          if (parent.keyName != child.keyName) {
            if (!alreadyPresentChild) {
              parent.children.push(child);
              parent = child;
            } else {
              parent = alreadyPresentChild;
            }
          }
        }
    
      });
    });
    
    console.log(JSON.stringify(output));