Find and replace object in array (based on id)
Solution 1
Use Array.map
and Array.find()
:
const allItems = [
{ 'id': 1, 'category_id': 1, 'text': 'old' },
{ 'id': 2, 'category_id': 1, 'text': 'old' }
];
const newItems = [
{ 'id': 1, 'category_id': 1, 'text': 'new', 'more_info': 'abcd' },
{ 'id': 2, 'category_id': 1, 'text': 'new', 'more_info': 'abcd' }
];
const result = allItems.map(x => {
const item = newItems.find(({ id }) => id === x.id);
return item ? item : x;
});
console.log(result);
This can even be shortened by using a logical or to return the original item when the call to find
returns undefined
:
const result = allItems.map(x => newItems.find(({ id }) => id === x.id) || x);
Regarding your code, you can't use indexOf
since it only compares primitive values or references in the case of arrays and objects.
Solution 2
Depending on how large your input arrays are, you might consider adding an intermediate step to build a "map" of your newItems
, where the key of this map is the id
of the item.
Using a mapping such as this would allow for much faster reconciliation (and replacement) of items from the allItems
array with items in the newItems
array:
function replaceItemsOnId(items, replacement) {
/*
Create a map where the key is the id of replacement items.
This map will speed up the reconciling process in the
subsequent "map" stage
*/
const replacementMap = replacement.reduce((map, item) => {
map[ item.id ] = item
return map;
}, {})
/*
Map the items to a new array where items in the result array
are either clones of the orignals, or replaced by items of
"replacement" array where thier id matches the item being mapped
*/
return items.map(item => {
const use = replacementMap[ item.id ] || item
return { ...use }
})
}
const allItems = [
{
'id': 1,
'category_id': 1,
'text': 'old',
},
{
'id': 2,
'category_id': 1,
'text': 'old'
}
]
const newItems = [
{
'id': 1,
'category_id': 1,
'text': 'new',
'more_info': 'abcd'
},
{
'id': 2,
'category_id': 1,
'text': 'new',
'more_info': 'abcd'
}
]
console.log(replaceItemsOnId(allItems, newItems))
Solution 3
Just use map
like so:
const allItems = [{
'id': 1,
'category_id': 1,
'text': 'old',
},
{
'id': 2,
'category_id': 1,
'text': 'old'
}
];
const newItems = [{
'id': 1,
'category_id': 1,
'text': 'new',
'more_info': 'abcd'
},
{
'id': 2,
'category_id': 1,
'text': 'new',
'more_info': 'abcd'
}
];
const replacedItems = allItems.map(e => {
if (newItems.some(({ id }) => id == e.id)) {
return newItems.find(({ id }) => id == e.id);
}
return e;
});
console.log(replacedItems);
Solution 4
Just using a simple Array.map and a method to check the other array.
const allItems = [
{
'id': 1,
'category_id': 1,
'text': 'old',
},
{
'id': 2,
'category_id': 1,
'text': 'old'
},
{
'id': 3,
'category_id': 1,
'text': 'old_same'
}
]
const newItems = [
{
'id': 1,
'category_id': 1,
'text': 'new',
'more_info': 'abcd'
},
{
'id': 2,
'category_id': 1,
'text': 'new',
'more_info': 'abcd'
}
]
const findNewItem = (oldItem) => newItems.find(item => item.id === oldItem.id);
let arr = allItems.map(item => findNewItem(item)||item);
console.log(arr);
Related videos on Youtube
jj008
Updated on September 15, 2022Comments
-
jj008 over 1 year
Got a bit of a puzzle here...I want to loop through
allItems
and returnallItems
but replace with anynewItems
that matches its id. How can I look for a match onid
and then replace it with the correct object into the array?const allItems = [ { 'id': 1, 'category_id': 1, 'text': 'old', }, { 'id': 2, 'category_id': 1, 'text': 'old' } ] const newItems = [ { 'id': 1, 'category_id': 1, 'text': 'new', 'more_info': 'abcd' }, { 'id': 2, 'category_id': 1, 'text': 'new', 'more_info': 'abcd' } ]
What I tried so far:
for(let i = 0; i < allItems.length; i++) { if(newItems.indexOf(allItems[i].id) > -1){ allItems[i] = newItems } }
How can I get the position of the object in
newItems
and then replace it intoallItems
?