bobbyrne01
bobbyrne01

Reputation: 6745

Accessing nested array at a dynamic depth

I have the following piece of json, it follows a specific pattern but each object can have any number of children and each of those children objects can have any number of children ..

[
  {
    "name": "1st level",
    "parentId": "",
    "id": "dummyvalue1",
    "children": [
      {
        "name": "2nd level child",
        "parentId": "dummyvalue1",
        "id": "dummyvalue2"
      },
      {
        "name": "another 2nd level child",
        "id": "dummyvalue3",
        "children": [
          {
            "name": "3rd level child",
            "id": "dummyvalue4",
            "children": [
              {
                "name": "4th level child",
                "parentId": "dummyvalue4",
                "id": "dummyvalue5"
              }
            ],
            "parentId": "dummyvalue3"
          }
        ],
        "parentId": "dummyvalue1"
      }
    ]
  }
]

The problem is, I only need to access objects at a specific depth within this nested object/array structure.

And that depth is dynamic.

If the depth equals 3, then I would like to add a new dummy object into the children array for that level. So the new structure would look like this ..

[
  {
    "name": "1st level",
    "parentId": "",
    "id": "dummyvalue1",
    "children": [
      {
        "name": "2nd level child",
        "parentId": "dummyvalue1",
        "id": "dummyvalue2"
      },
      {
        "name": "another 2nd level child",
        "id": "dummyvalue3",
        "children": [
          {
            "name": "3rd level child",
            "id": "dummyvalue4",
            "children": [
              {
                "name": "4th level child",
                "parentId": "dummyvalue4",
                "id": "dummyvalue5"
              }
            ],
            "parentId": "dummyvalue3"
          },
          {
            "name": "NEW OBJECT",
            "parentId": "dummyvalue3",
            "id": "random"
          }
        ],
        "parentId": "dummyvalue1"
      }
    ]
  }
]

Is there a clean way to do this? Instead of huge loops trying to iterate to the right level. Also dont think I can use dot notation since the number of levels and the depth variable is dynamic

Upvotes: 0

Views: 201

Answers (1)

Erazihel
Erazihel

Reputation: 7605

I've created this function:

function addChild(currentChild, childToAdd, depth) {
  if (depth === 1) {
    currentChild.children.push(childToAdd);
    return;
  }

  const nextChild = currentChild.children.filter(child => child.children && child.children.length)[0];

  if (!nextChild) {
     if (currentChild.children && currentChild.children.length) {
       currentChild.children[0].children = [childToAdd];
     } else {
       currentChild.children = [childToAdd];
     }
     return;
  }

  addChild(nextChild, childToAdd, depth - 1);
}

It takes 3 arguments:

  1. The current child
  2. The child to add
  3. The remaining depth to run through

If the depth is 1, it simply add the child to the children. If not, it looks inside the children, take the first one with children and make a recursive call to the same function.

const data = [
  {
    "name": "1st level",
    "parentId": "",
    "id": "dummyvalue1",
    "children": [
      {
        "name": "2nd level child",
        "parentId": "dummyvalue1",
        "id": "dummyvalue2"
      },
      {
        "name": "another 2nd level child",
        "id": "dummyvalue3",
        "children": [
          {
            "name": "3rd level child",
            "id": "dummyvalue4",
            "children": [
              {
                "name": "4th level child",
                "parentId": "dummyvalue4",
                "id": "dummyvalue5"
              }
            ],
            "parentId": "dummyvalue3"
          }
        ],
        "parentId": "dummyvalue1"
      }
    ]
  }
]

function addChild(currentChild, childToAdd, depth) {
  if (depth === 1) {
    currentChild.children.push(childToAdd);
    return;
  }
  
  const nextChild = currentChild.children.filter(child => child.children && child.children.length)[0];
  
  if (!nextChild) {
     if (currentChild.children && currentChild.children.length) {
       currentChild.children[0].children = [childToAdd];
     } else {
       currentChild.children = [childToAdd];
     }
     return;
  }

  addChild(nextChild, childToAdd, depth - 1);
}

addChild(data[0], {foo: 'bar'}, 3);
addChild(data[0], {bar: 'baz'}, 2);
addChild(data[0], {baz: 'foo'}, 1);
addChild(data[0], {extraChild: 'foo'}, 4);


console.log(data);

Upvotes: 1

Related Questions