1

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?

4
  • My answer on a similar question: tree from array of dot-separated strings Commented Oct 23, 2021 at 12:42
  • Your solution works, but it just adds a nested label. I need to add nested objects. Commented Oct 23, 2021 at 13:07
  • You just need to tweak a little. Instead of splitting the string, you need to split the property: for (const obj of data) { let splits = obj.DEPENDENCY.split('.') And instead of const o = { label }, you need const o = { ...obj } Commented Oct 24, 2021 at 14:56
  • Here's a fiddle: jsfiddle.net/adigas/7etafd25 Commented Oct 24, 2021 at 15:03

1 Answer 1

3

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 
Sign up to request clarification or add additional context in comments.

3 Comments

Ok now one more thing. How do I search for a name on the nested array and extract it to a single object? For example, let's say I search for the object with NAME = initArray4. Which is inside initArray2 object, which is inside initArray object. How to filter the whole nested array and keep only the initArray4 object?
@iNemesis I added the searchByName function. Searching (and/or traversing) is core to a nested/tree-like data structure. I suggest you read about tree/nested data structures and related algorithms
Thank you so much for your replies. I definitely will read about tree/nested data structures for better understanding your code. Once again, i really appreciate your time

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.