How to convert a raw data into hierarchical structure

Solution 1:

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));

Solution 2:

You can build the hierarchy as follows. By keeping a map, keyed by path, you can quickly check whether you already have a node for the current value, or need to create one and add it to the parent's children list:

function createHierarchy(data) {
    let tree = { children: [] };
    let keys = {};
    for (let item of Object.values(data)) {
        let node = tree;
        let key = "";
        for (let keyName of ["chancellor", "viceChancellor", "headProfessor", "student", "intern"]) {
            let name = item[keyName];
            if (name == null) break;
            key += "/" + name;
            let child = keys[key]; // Fast lookup
            if (!child) {
                child = keys[key] = { keyName, name };
                (node.children ??= []).push(child);
            }
            node = child;
        }
    }
    return tree.children;
}

// Demo
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",},};

console.log(createHierarchy(data));