Home > Blockchain >  JavaScript nested loop - replaced by .map() and .some() methods
JavaScript nested loop - replaced by .map() and .some() methods

Time:09-29

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; }

  • Related