Intersect between two arrays of objects and keep only matched element and delete the non-matching element based on key of object
Intersect between two arrays of objects and keep only matched element and delete the non-matching element based on key of object
I have two arrays of objects and I need to intersect between the arrays to find out the common one and delete it from the first array which does not have the same item based on one of the keys.
Note that I want to mutate the first array itself.
Here is my code sample and what I tried with .map
but did not get the expected result.
.map
(() => {
const first = Array.from({ length: 5 }, (_, i) => ({
id: `in-${i}`,
name: "one",
age: `${i * 5}`
}));
const second = Array.from({ length: 3 }, (_, i) => ({
id: `in-${i}`,
name: "two"
}));
console.log({ first });
console.log({ second });
const sid = second.map(s => s.id);
first.map((f, i) => {
if (sid.includes(f.id)) {
console.log("✔️ included");
} else {
console.log("👎🏻 not included");
first.splice(i, 1);
}
});
console.log("...now...");
console.log({ first });
console.log({ second });
})();
This does not delete the last array element of first array.
Expected output:
[ { id: 'in-0', name: 'one', age: '0' },
{ id: 'in-1', name: 'one', age: '5' },
{ id: 'in-2', name: 'one', age: '10' }
] }
Actual output:
[ { id: 'in-0', name: 'one', age: '0' },
{ id: 'in-1', name: 'one', age: '5' },
{ id: 'in-2', name: 'one', age: '10' },
{ id: 'in-4', name: 'one', age: '20' } ] }
What mistake am I doing here? Kindly help.
Also, suggest any other shorter and simplified ways. I think I can use .reduce
/ forEach here but I do not know how.
.reduce
no sorry I just missed it
– Pointy
Jun 29 at 17:06
The issue probably has something to do with the fact that you're changing the array in the middle of the
.map()
call.– Pointy
Jun 29 at 17:07
.map()
yes, my guess is the same but how to achieve the expected output? I do not want to assign the result into new array neither can do
first = first.map(..)
so I have to change the first array itself– pro.mean
Jun 29 at 17:09
first = first.map(..)
2 Answers
2
When you get past element 2, your callback will remove element 3. That was index 4 in the array, so the next iteration removes element 5. Element 4 is skipped because the innards of .map()
don't know that you're mutating the array.
.map()
I personally would just use a simple for
loop if you don't want to make a new array:
for
for (let i = first.length; --i >= 0; ) {
if (!sid.includes(first[i].id))
first.splice(i, 1);
}
If you loop from the end towards the start, splicing elements out doesn't mess things up.
Thanks. can I use
for..in
or for..of
loop here– pro.mean
Jun 29 at 17:19
for..in
for..of
you can use .filter()
.filter()
const result = first.filter(f => sid.includes(f.id) );
if you want to mutate the first
array, don't use const
, replace it with a let
and overwrite it like :
first
const
let
first = first.filter(f => sid.includes(f.id));
(() => {
// replace const with let
let first = Array.from({
length: 5
}, (_, i) => ({
id: `in-${i}`,
name: "one",
age: `${i * 5}`
}));
const second = Array.from({
length: 3
}, (_, i) => ({
id: `in-${i}`,
name: "two"
}));
const sid = second.map(s => s.id);
// use .filter and overwrite the first array
first = first.filter(f => sid.includes(f.id));
console.log(first);
})();
I agree that this would be the right thing to do, but the OP apparently wants to mutate the first array.
– Pointy
Jun 29 at 17:10
sorry but I could not assign
first = first.filter
in this specific problem.– pro.mean
Jun 29 at 17:11
first = first.filter
@pro.mean i see, in that case i would've suggest a simple
for
loop and splice
but @Pointy beat me to it.– Taki
Jun 29 at 17:15
for
splice
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
I have added the code snippet. do I need to add input again?
– pro.mean
Jun 29 at 17:03