Reputation: 1083
Got a bit of a puzzle here...I want to loop through allItems
and return allItems
but replace with any newItems
that matches its id. How can I look for a match on id
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 into allItems
?
Upvotes: 12
Views: 23770
Reputation: 909
The answers for this question mostly have the code iterating through all the items in the original array to see which should be replaced. If the original array is large, and you don't need to replace many, it might be better performance to change the logic. I only needed to replace one item in an array (customers). I did it like this:
const index = customers.findIndex(x => x.Id == editedCust.Id);
if (index >= 0)
customers[index] = editedCust;
You could iterate through all the items in newItems and do the above for each.
Upvotes: 0
Reputation: 71
You could get a reference to the object you are looking for by id but that would not be enough because then you would need the index in order to replace it in allItem (allItem[index] = newItem
), so I suggest finding that index instead first like this:
for (let item of newItems) {
let indexNewItem = allItems.map(function (e) { return e.id }).indexOf(item.id);
allItems[indexNewItem] = item
}
this should work
Upvotes: 0
Reputation: 13964
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.
Upvotes: 16
Reputation: 30360
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))
Upvotes: 1
Reputation: 4768
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);
Upvotes: 1
Reputation: 44087
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);
Upvotes: 1