Reputation: 1895
I'm trying to recursively search through an array for an object by its unique id, then push an object into its parts array, then return the entire array
For example, this is the array I want to search:
car = [
{
id: 13,
title: 'Component13',
parts: [
{
id: 784,
title: 'Component242',
parts: [
]
},
{
id: 9,
type: 'mitigation',
parts: [
{
id: 68,
type: 'mitigation22',
parts: [
]
},
{
id: 88,
type: 'threat',
parts: [
]
}
]
}
]
},
{
id: 3,
title: 'Component13',
parts: [
{
id: 60,
title: 'Component34',
parts: [
]
},
{
id: 51,
type: 'threat',
parts: [
{
id: 38,
type: 'mitigation22',
parts: [
]
}
]
}
]
}
]
And if I wanted to insert this object into the parts child array in id 38:
{
id: 34,
title: 'Component211',
parts: [
]
}
... the result should be this:
...commented out the first block to save space
{
id: 3,
title: 'Component13',
parts: [
{
id: 60,
title: 'Component34',
parts: [
]
},
{
id: 51,
type: 'threat',
parts:[
{
id: 38,
type: 'mitigation22',
parts: [
{
id: 34,
title: 'Component211',
parts: [
]
}
]
}
]
}
]
}
What is the best way to do this considering that I might need to insert an object at any level on the car array?
My feeble attempt:
const updatePart = (id, obj, car) => {
for (var i = 0; i < car.length; i++) {
if (car[i].id == id) {
car[i].parts.push(obj)
} else {
car[i].parts.map(function (item) {
updatePart(id, obj, item)
})
}
return car
}
}
car = updateTree(id, obj, car);
Upvotes: 1
Views: 1123
Reputation: 386560
If you like to get a new array, you could map the objects with new parts
properties.
const
update = (array, id, object) => array.map(o => o.id === id
? { ...o, parts: [...o.parts, object] }
: { ...o, parts: update(o.parts, id, object) }
);
var car = [{ id: 13, title: 'Component13', parts: [{ id: 784, title: 'Component242', parts: [] }, { id: 9, type: 'mitigation', parts: [{ id: 68, type: 'mitigation22', parts: [] }, { id: 88, type: 'threat', parts: [] }] }] }, { id: 3, title: 'Component13', parts: [{ id: 60, title: 'Component34', parts: [] }, { id: 51, type: 'threat', parts: [{ id: 38, type: 'mitigation22', parts: [] }] }] }],
result = update(car, 38, { id: 34, title: 'Component211', parts: [] });
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
A mutating approach with a short circuit if the id
is found.
const
update = (array, id, object) => array.some(o => o.id === id
? o.parts.push(object)
: update(o.parts, id, object)
);
var car = [{ id: 13, title: 'Component13', parts: [{ id: 784, title: 'Component242', parts: [] }, { id: 9, type: 'mitigation', parts: [{ id: 68, type: 'mitigation22', parts: [] }, { id: 88, type: 'threat', parts: [] }] }] }, { id: 3, title: 'Component13', parts: [{ id: 60, title: 'Component34', parts: [] }, { id: 51, type: 'threat', parts: [{ id: 38, type: 'mitigation22', parts: [] }] }] }];
update(car, 38, { id: 34, title: 'Component211', parts: [] });
console.log(car);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 2
Reputation: 4488
Your updatePart
is expecting an array, but in your map
you are using recursion sending objects. So you don't need to use map
(or forEach
, which would be best suitable here) at all:
var car=[{id:13,title:"Component13",parts:[{id:784,title:"Component242",parts:[]},{id:9,type:"mitigation",parts:[{id:68,type:"mitigation22",parts:[]},{id:88,type:"threat",parts:[]}]}]},{id:3,title:"Component13",parts:[{id:60,title:"Component34",parts:[]},{id:51,type:"threat",parts:[{id:38,type:"mitigation22",parts:[]}]}]}];
const updatePart = (id, obj, car) => {
for (var i = 0; i < car.length; i++) {
console.log(car[i])
if (car[i].id == id) {
car[i].parts.push(obj)
} else {
updatePart(id, obj, car[i].parts)
}
}
return car
}
const obj = {
id: 34,
title: 'Component211',
parts: [
]
}
car = updatePart(38, obj, car);
console.log(car)
Other errors in your code arereturn car
inside loop, you should return after loop completes and you declared updatePart
not updateTree
.
Upvotes: 0
Reputation: 22237
Perhaps consider a lookup object to store a flat list of references to the nodes in your tree:
let memo = {};
const buildMemo = (arr) => {
arr.forEach(item => {
memo[item.id] = item;
if (item.parts) buildMemo(item.parts);
}
};
buildMemo(car);
Now, if you need to do some operation on the node of your car
tree with id = 34, you can get a reference from memo[34]. You would need logic to update memo if you add/remove/move nodes from the car
array
Upvotes: 0