I have two arrays like this
let array1 = [{
'id': 1,
'name': 'A'
}, {
'id': 2,
'name': 'B'
}, {
'id': 3,
'name': 'C'
}]
let array2 = [{
'id': 1,
'name': 'x'
}, {
'id': 2,
'name': 'y'
}]
I want to update array 1 with the array 2 object values which are matching based on id values. Result would be something like this.
[{
'id': 1,
'name': 'x'
}, {
'id': 2,
'name': 'y'
}, {
'id': 3,
'name': 'C'
}]
I have written something like this but not working .
array1.forEach(item1 => {
const itemFromArr2 = array2.find(item2 => item2.id== item1.id);
if (itemFromArr2) {
item1= itemFromArr2;
}
}
)
Please suggest me how to do this.
CodePudding user response:
You might want to check this one-liner out:
array1.map(e => (e.name = array2.find(a => a.id == e.id)?.name || e.name, e));
Explanation: We are mapping over array1 and searching for the matching id in array2, if it is found (array2.find(a => a.id == e.id)?.name
), we override the name property (e.name = ...
), otherwise we keep it as it is (... || e.name
).
Small example:
let array1 = [{
'id': 1,
'name': 'A'
}, {
'id': 2,
'name': 'B'
}, {
'id': 3,
'name': 'C'
}]
let array2 = [{
'id': 1,
'name': 'x'
}, {
'id': 2,
'name': 'y'
}]
const newarray = array1.map(e => (e.name = array2.find(a => a.id == e.id)?.name || e.name, e));
console.log(newarray);
Edit according to @Roster's comment, if you want to override the whole entry use this line:
array1.map(e => (e = array2.find(a => a.id == e.id) || e, e));
Second example:
let array1 = [{
'id': 1,
'name': 'A'
}, {
'id': 2,
'name': 'B'
}, {
'id': 3,
'name': 'C'
}]
let array2 = [{
'id': 1,
'name': 'x'
}, {
'id': 2,
'name': 'y',
'otherproperty': 42
}]
const newarray = array1.map(e => (e = array2.find(a => a.id == e.id) || e, e));
console.log(newarray);
CodePudding user response:
Using a hashmap
to update the array.
The reason of hashmap
is for performance.
const array1 = [
{ id: 1, name: "A" },
{ id: 2, name: "B" },
{ id: 3, name: "C" },
];
const array2 = [
{ id: 1, name: "x" },
{ id: 2, name: "y" },
];
const hashMap2 = array2.reduce((carry, item) => {
const { id } = item;
if (!carry[id]) {
carry[id] = item;
}
return carry;
}, {});
const output = array1.map(item => {
const newName = hashMap2[item.id]?.name;
if (newName) {
item.name = newName;
}
return item;
});
console.log(output);
CodePudding user response:
Here's a solution using Generics:
const array1 = [{
'id': 1,
'name': 'A'
}, {
'id': 2,
'name': 'B'
}, {
'id': 3,
'name': 'C'
}]
const array2 = [{
'id': 1,
'name': 'x'
}, {
'id': 2,
'name': 'y'
}]
function mergeArray<T>(arr1: T[], arr2: T[], identifier: keyof T): T[] {
for(const oItem of arr2){
const itemInArr1 =
arr1.find(item => item[identifier] === oItem[identifier]);
if(itemInArr1){
for(const key in itemInArr1){
itemInArr1[key] = oItem[key];
}
} else {
arr1.push(oItem);
}
}
return arr1;
}
console.log(mergeArray(array1,array2, 'id'));
This iterates over the itmes in array2
and checks their existence inside array1
based on the identifier.
Based on whether or not the item exists in array1
, the item will be modified, or the item from array2
is pushed into array1
.
CodePudding user response:
Convert the update
array to a Map
, then iterate the target
array with Array.map()
, and merge it with the object of the same key in the upateMap
if it exists:
const fn = (predicate, target, update) => {
const updateMap = new Map(update.map(o => [predicate(o), o]))
return target.map(o => {
const key = predicate(o)
return updateMap.has(key)
? { ...o, ...updateMap.get(key)}
: o
})
}
const array1 = [{"id":1,"name":"A"},{"id":2,"name":"B"},{"id":3,"name":"C"}]
const array2 = [{"id":1,"name":"x"},{"id":2,"name":"y"}]
const result = fn(o => o.id, array1, array2);
console.log(result);
With types (TS playground):
const fn = <T>(predicate: (arg: T) => any, target: T[], update: T[]) => {
const updateMap = new Map(update.map(o => [predicate(o), o]))
return target.map(o => {
const key = predicate(o)
return updateMap.has(key)
? { ...o, ...updateMap.get(key)}
: o
})
}