1

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.

(() => {
  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.

4
  • I have added the code snippet. do I need to add input again? Commented Jun 29, 2018 at 17:03
  • no sorry I just missed it Commented Jun 29, 2018 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. Commented Jun 29, 2018 at 17:07
  • 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 Commented Jun 29, 2018 at 17:09

2 Answers 2

3

you can use .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 = 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);

})();

Sign up to request clarification or add additional context in comments.

3 Comments

I agree that this would be the right thing to do, but the OP apparently wants to mutate the first array.
sorry but I could not assign first = first.filter in this specific problem.
@pro.mean i see, in that case i would've suggest a simple for loop and splice but @Pointy beat me to it.
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.

I personally would just use a simple for loop if you don't want to make a new array:

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.

1 Comment

Thanks. can I use for..in or for..of loop here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.