Reputation: 151
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",
},
],
},
],
},
],
},
],
},
];
Upvotes: 0
Views: 534
Reputation: 350137
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));
Upvotes: 1
Reputation: 150
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));
Upvotes: 1