Home > Blockchain >  Nested arrays and targeting array by keys
Nested arrays and targeting array by keys

Time:10-13

I'm really not sure how to word this issue but I will try my best.

I have a nested array:

const items = [
  {
    id: 1,
    name: "Test name",
    children: [
      {
        id: 5,
        name: "Test name 5",
        children: [
          {
            id: 6,
            name: "Test name 6",
            children: [],
          },
        ],
      },
    ],
  },
  {
    id: 8,
    name: "Test name 8",
    children: [
      {
        id: 9,
        name: "Test name 9",
        children: [],
      },
    ],
  },
];

and I have an array of indexes where to target and update

const keys = [0,0,0]

The array of indexes should target Test name 6

How can I update Test name 6 to something else?

p.s. items and keys are dynamic. there might be dozens of nested items or dozens of indexes in keys

CodePudding user response:

You could reduce the indices and check the children property.

After getting the final object, just assign the value to the wanted property.

const
    getItem = (children, keys) => keys.reduce(
        ({ children = [] }, i) => children[i],
        { children }
    ),
    items = [{ id: 1, name: "Test name", children: [{ id: 5, name: "Test name 5", children: [{ id: 6, name: "Test name 6", children: [] }] }] }, { id: 8, name: "Test name 8", children: [{ id: 9, name: "Test name 9", children: [] }] }],
    keys = [0, 0, 0];
    
console.log(getItem(items, keys));

CodePudding user response:

To update your nested array first you will first need to change it to a mutable variable, i.e. from a const to a let or var.

From there you can update the value with something like:

// Copy pasted data from your post
let items = [
  {
    id: 1,
    name: "Test name",
    children: [
      {
        id: 5,
        name: "Test name 5",
        children: [
          {
            id: 6,
            name: "Test name 6",
            children: [],
          },
        ],
      },
    ],
  },
  {
    id: 8,
    name: "Test name 8",
    children: [
      {
        id: 9,
        name: "Test name 9",
        children: [],
      },
    ],
  },
];

const keys = [0,0,0]

// <----------------- CODE BELOW ---------------->

// var to store item each time you dive deeper into the nested array
// initalize with the first item
let item = items[keys[0]].children;

// loop through each key
for(let i = 1; i < keys.length; i  ){
  // if we are at the last key, set item equal to the item object
  if(i == keys.length-1){
    item = item[keys[i]];
  }
  // otherwise, set item equal to the item's children
  else{
    item = item[keys[i]].children
  }
}

// once item has been reached - all keys have been looped through - data can be minupulated
item.name = "new value"
// "Test name 6" has been updated to "new value"

emphasized text

CodePudding user response:

In this scenario, I usually use a Map referencing the items within the nested arrays. For example:

const items = [
  {
    id: 1,
    name: "Test name",
    children: [
      {
        id: 5,
        name: "Test name 5",
        children: [
          {
            id: 6,
            name: "Test name 6",
            children: [],
          },
        ],
      },
    ],
  },
  {
    id: 8,
    name: "Test name 8",
    children: [
      {
        id: 9,
        name: "Test name 9",
        children: [],
      },
    ],
  },
];

const createItemsMap = items => {
  const m = new Map();
  
  (function _collect(items) {
    for (const item of items) {
      m.set(item.id, item);
      if (item.children) {
        _collect(item.children);
      }
    }
  })(items);
  
  return m;
}

const itemsMap = createItemsMap(items);

// modify item #6
itemsMap.get(6).name = "Modified name 6";

console.log("itemsMap.get(1) === items[0] is", itemsMap.get(1) === items[0]);
console.log(items);

With that map, modifying the items is simply a matter of doing this :

const item = itemsMap.get(id);

item.name = "Foo";

To get the keys of that map :

const keys = Array.from(itemsMap.keys());

Note: If items is modified directly (i.e. items are added or removed), then itemsMap needs to be re-generated. In any other case, both items and itemsMap reference to the same data.

  • Related