I get some data in a flat array and I want to nest one inside another.
The attribute which defines the depth of an object is the DEPENDENCY where I split it in so as to get the different levels of nesting.
This is the data I get
const initArray = [
{ NAME: "initArray", DEPENDENCY: "0", VAR1: "VAR1", VAR2: "VAR2" },
{ NAME: "initArray2", DEPENDENCY: "0.0", VAR1: "VAR1", VAR2: "VAR2" },
{ NAME: "initArray3", DEPENDENCY: "0.1", VAR1: "VAR1", VAR2: "VAR2" },
{ NAME: "initArray4", DEPENDENCY: "0.0.0", VAR1: "VAR1", VAR2: "VAR2" },
{ NAME: "initArray5", DEPENDENCY: "0.0.1", VAR1: "VAR1", VAR2: "VAR2" },
{ NAME: "initArray6", DEPENDENCY: "0.0.2", VAR1: "VAR1", VAR2: "VAR2" },
{ NAME: "initArray7", DEPENDENCY: "0.1.1", VAR1: "VAR1", VAR2: "VAR2" },
{ NAME: "initArray8", DEPENDENCY: "0.1.2", VAR1: "VAR1", VAR2: "VAR2" },
{ NAME: "initArray9", DEPENDENCY: "0.1.3", VAR1: "VAR1", VAR2: "VAR2" },
{ NAME: "initArray10", DEPENDENCY: "0.1.4", VAR1: "VAR1", VAR2: "VAR2" },
{ NAME: "initArray11", DEPENDENCY: "0.1.5", VAR1: "VAR1", VAR2: "VAR2" },
];
and this the expected result
const myArray = [
{
NAME: "initArray",
DEPENDENCY: "0",
VAR1: "VAR1",
VAR2: "VAR2",
CHILDREN: [
{
NAME: "initArray2",
DEPENDENCY: "0.0",
VAR1: "VAR1",
VAR2: "VAR2",
CHILDREN: [
{
NAME: "initArray4",
DEPENDENCY: "0.0.0",
VAR1: "VAR1",
VAR2: "VAR2",
},
{
NAME: "initArray5",
DEPENDENCY: "0.0.1",
VAR1: "VAR1",
VAR2: "VAR2",
},
{
NAME: "initArray6",
DEPENDENCY: "0.0.2",
VAR1: "VAR1",
VAR2: "VAR2",
},
],
},
{
NAME: "initArray3",
DEPENDENCY: "0.1",
VAR1: "VAR1",
VAR2: "VAR2",
CHILDREN: [
{
NAME: "initArray7",
DEPENDENCY: "0.1.1",
VAR1: "VAR1",
VAR2: "VAR2",
},
{
NAME: "initArray8",
DEPENDENCY: "0.1.2",
VAR1: "VAR1",
VAR2: "VAR2",
},
{
NAME: "initArray9",
DEPENDENCY: "0.1.3",
VAR1: "VAR1",
VAR2: "VAR2",
},
{
NAME: "initArray10",
DEPENDENCY: "0.1.4",
VAR1: "VAR1",
VAR2: "VAR2",
},
{
NAME: "initArray11",
DEPENDENCY: "0.1.5",
VAR1: "VAR1",
VAR2: "VAR2",
},
],
},
],
},
];
This can be done by the following code
let myArray = Array();
Object.keys(initArray).map((key) => {
const dependencyTree = initArray[key].DEPENDENCY.split(".");
if (dependencyTree.length === 1) {
myArray[Number(dependencyTree[0])] = initArray[key];
} else if (dependencyTree.length === 2) {
if (!myArray[Number(dependencyTree[0])].hasOwnProperty("CHILDREN")) {
myArray[Number(dependencyTree[0])].CHILDREN = Array();
}
myArray[Number(dependencyTree[0])].CHILDREN[Number(dependencyTree[1])] = initArray[key];
} else if (dependencyTree.length === 3) {
if (!myArray[Number(dependencyTree[0])].CHILDREN[Number(dependencyTree[1])].hasOwnProperty("CHILDREN")) {
myArray[Number(dependencyTree[0])].CHILDREN[Number(dependencyTree[1])].CHILDREN = Array();
}
myArray[Number(dependencyTree[0])].CHILDREN[Number(dependencyTree[1])].CHILDREN.push(initArray[key]);
}
});
but I would like a solution for nesting regardless the depth. Now I have to add manually the if statement for each depth level. Is there any workaround?
1 Answer 1
Nesting a flat list with arbitrary depth has common recursive algorithm.
The code below is a working example with your dataset.
Another thing to keep in mind is that this code does NOT mutate your original flat list
function generateNesting(originalList, nestedList) {
return nestedList.map((item) => {
const { DEPENDENCY: parentDependency } = item;
const childItems = originalList.filter((item) => item.DEPENDENCY.startsWith(parentDependency) && item.DEPENDENCY.length - 2 === parentDependency.length);
return { ...item, CHILDREN: generateNesting(originalList, childItems) };
});
}
function makeNested(list) {
const rootItems = list.filter((item) =>
item.DEPENDENCY.length === 1
);
return generateNesting(list, rootItems);
}
function searchByName(name, nestedList = []) {
for(let i = 0; i < nestedList.length; i++) {
const { NAME, CHILDREN } = nestedList[i]
if(NAME === name) {
return nestedList[i]
}
const found = searchByName(name, CHILDREN)
if(found) {
return found
}
}
}
const result = makeNested(initArray) // initArray is your flat list
console.log(searchByName('initArray3', result))
console.log(searchByName('initArray10', result))
console.log(searchByName('initArrayISNOTPRESENT', result)) // prints undefined
for (const obj of data) { let splits = obj.DEPENDENCY.split('.')And instead ofconst o = { label }, you needconst o = { ...obj }