0

I have a data structure like this:

[
    {name: "Bob"},
    {name: "Ashley"},
    {name: "Jack", children: [
        {name: "Sinclair"},
        {name: "Laura"}
    ]},
    {name: "Stuart", children: [
        {name: "Trevor", children: [
            {name: "Woody"},
            {name: "Crystal"}
        ]},
        {name: "Allen"}
    ]}
]

There can be virtually unlimited levels of nesting.

What I'm trying to do: given one of the objects in this data structure, I want to add another object after it. For example, if given the name "Woody", the object I'm inserting needs to go between Woody and Crystal.

I already have a method for recursively iterating through the data structure to find an object when given a name (names are unique in this scenario). I'm just looking for a way to modify the entire data structure when something is inserted at an arbitrary location inside one of the nested arrays.

The only way I've been able to think of was to flatten the entire data structure first using JSON.stringify, then flatten the object I'm inserting, then inserting it into the string, then converting the string back to an object. The issue with that is that JSON.stringify can be very slow for large objects, and performance is a priority here.

Ege Ersoz
  • 6,461
  • 8
  • 34
  • 53
  • 2
    During your recursive search you have reference to the children (or parent) arrays at each level so it should be straightforward to `splice()` a new element into that array. Show us your recursion attempt – charlietfl Feb 28 '21 at 00:00
  • Can you elaborate on how you know which parent the "woody" object should be added to? What is the instructions/parameters? – JAM Feb 28 '21 at 00:03
  • What if you have two people called `Woody`? – Nick Feb 28 '21 at 00:22
  • @Nick Names are always unique in my scenario. – Ege Ersoz Feb 28 '21 at 00:35
  • @JAM I'm not adding a "Woody" object. The given instruction is "add X object after the object that has name 'Woody'". – Ege Ersoz Feb 28 '21 at 00:36

1 Answers1

0

With a recursive function with a loop that searches through each object in a given children array, you can either look for the matching object - or, if the item has a children, make the recursive call:

const data = [
    {name: "Bob"},
    {name: "Ashley"},
    {name: "Jack", children: [
        {name: "Sinclair"},
        {name: "Laura"}
    ]},
    {name: "Stuart", children: [
        {name: "Trevor", children: [
            {name: "Woody"},
            {name: "Crystal"}
        ]},
        {name: "Allen"}
    ]}
];

const nameToFind = 'Sinclair';
const insert = (arr) => {
  for (let i = 0; i < arr.length; i++) {
    if (arr[i].name === nameToFind) {
      arr.splice(i + 1, 0, { name: 'newName' });
      return true;
    }
    if (arr[i].children) {
      const found = insert(arr[i].children);
      if (found) return true;
    }
  }
};
insert(data);
console.log(data);

Another option would be to use findIndex to find a match in the array, and splice the item in at the index if found, otherwise loop again to go through all children in the array, but that'd require iterating over every item twice (and for loops are the fastest anyway if performance is the priority)

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320