I have two arrays, I'm trying to update the object of the first array with the object from the second array if name is changed. I can do that with nested loop but I can't figured out with .map() and .some() methods
const result1 = [{
"id": 1,
"name": "name1"
},
{
"id": 2,
"name": "name2"
}]
const result2 = [{
"id": 1,
"name": "name1"
},
{
"id": 2,
"name": "changed"
}]
Here is the nested loop version that works:
for (i = 0; i < result1.length; i ) {
for (ii = 0; ii < result2.length; ii ) {
if (result1[i].id == result2[ii].id && result1[i].name !== result2[ii].name) {
result1[i].name = result2[ii].name
}
}
}
console.log(result1)
I get the correct result:
result1 = [ { id: 1, name: 'result1_name1' }, { id: 2, name: 'changed' } ]
And now I tried:
result1.map(res1 => {
let response = !result2.some(res2 => res1.name === res2.name)
if (response) {
res1.name = res2.name
}
return response
})
console.log(result1)
But I get an error:
ReferenceError: res2 is not defined
How can I do that?
Edit: Sorry, I changed to first paragraph because my issue was a bit different
CodePudding user response:
res2
is only accessible in the scope of the callback
provided to .some()
. Therefore it's undefined outside that scope.
And secondly, I think there's a logic error in your comparison. It seems like you need to compare the values as well as the IDs of the records.
const result1 = [ { id: 1, name: "name1" }, { id: 2, name: "name2" } ],
result2 = [ { id: 1, name: "name1" }, { id: 2, name: "changed" } ];
const changedResult1 = result1.map(item => ({
...item,
name: result2.find(item2 => item2.id === item.id)?.name || item.name
}))
console.log(changedResult1)
CodePudding user response:
One approach is to create a dictionary of result2(where id will be key & name as value) & then put map on result1 to get the desired result.
const result1 = [{"id": 1, "name": "name1"},{"id": 2,"name": "name2"}];
const result2 = [{"id": 1, "name": "name1"},{"id": 2,"name": "changed"}];
const dict = Object.fromEntries(result2.map(o=>[o.id, o.name]));
const updated = result1.map(o=>({...o, name:dict[o.id] }));
console.log(updated);
CodePudding user response:
Because you did not declare res2 in your res1 map.
You can find it with filter as ;
result1.map(res1 => {
let response = result2.filter(res2 => res1.name !== res2.name)
if (response.length > 0) {
res1.name = response[0].name
}
return response
})
console.log(result1)
CodePudding user response:
You can simply iterate result2
with forEach
, replacing the corresponding (by id
) object's name in result1
with the one from result2
:
const result1 = [{
"id": 1,
"name": "name1"
},
{
"id": 2,
"name": "name2"
}]
const result2 = [{
"id": 1,
"name": "name1"
},
{
"id": 2,
"name": "changed"
}]
result2.forEach(({ id, name }) => result1[result1.findIndex(o => o.id == id)].name = name)
console.log(result1)
Note that it's safe to always copy the name
from result2
as if it is the same, it will not affect the value in result1
.
CodePudding user response:
You could use Array.reduce()
to group the items by id
using a Map
.
const result1 = [{ "id": 1, "name": "name1" }, { "id": 2, "name": "name2" }]
const result2 = [{ "id": 1, "name": "name1" }, { "id": 2, "name": "changed" }]
const result = [...([...result1, ...result2].reduce((map, item) => {
return map.set(item.id, item);
}, new Map())).values()]
console.log('Result:', result)
.as-console-wrapper { max-height: 100% !important; }