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.