GoonGamja
GoonGamja

Reputation: 2286

How to find a way that filter an array compare to another array

I am trying to filter an array by compare it to another array and return an element that is missing from the second array.

The same element may occur multiple times, and each occurrence should either have a corresponding occurrence in the second array or be considered missing from the second array.

Here is an example.

example 1:
const participant = ['mario', 'zelda', 'ken', 'sonic'];
const completion = ['zelda', 'ken', 'mario'];

// return 'sonic' because the name is not inside of completion array

example 2:
const participant = ['mario', 'zelda', 'ken', 'sonic'];
const completion = ['mario', 'ken', 'sonic'];

// return 'zelda', the name is not inside of the array

example 3:
const participant = ['mario', 'zelda', 'ken', 'mario'];
const completion = ['mario', 'zelda', 'ken'];

// this time return 'mario' because only one 'mario' is inside of the array (think of this as another person with the same name)

And this is how I try to solve it

// iteration participant array inside completion array and if completion array find first same element inside participant array, remove that element

const solution = (participant, completion) => {
  completion.find(c => {
    participant.forEach((p, idx) => {
      if (c === p) {
        participant.splice(idx, idx+1)
      }
    })
  })
}

However this code only works in example 1 and 2, example 3 returns an empty array.

Thought using find method finds first element inside of an array that matches with element I want to find but it does not work way I expected.

Did I misuse find method?

Upvotes: 2

Views: 66

Answers (2)

Scott Sauyet
Scott Sauyet

Reputation: 50807

Update

Mea culpa. I didn't read the question closely enough. Here is another version

const removeEl = (xs, e, index = xs.indexOf(e)) =>
  index < 0 ? xs : [... xs .slice (0, index), ... xs .slice (index + 1)]

const removeAll = (xs = [], [e = undefined, ...es] = []) => 
  e == undefined ? xs : removeAll (removeEl(xs, e), es)

console.log(removeAll (['mario', 'zelda', 'ken', 'sonic'], ['zelda', 'ken', 'mario']))
console.log(removeAll (['mario', 'zelda', 'ken', 'sonic'], ['mario', 'ken', 'sonic']))
console.log(removeAll (['mario', 'zelda', 'ken', 'mario'], ['mario', 'zelda', 'ken']))

removeEl returns a new array like the original but with the first copy of the given element removed.

removeAll recursively calls itself for each element to be removed, using removeEl to create the list it passes to the recursive call.

If you have really long lists to remove, then we should do an imperative loop in place of the recursion, as JS recursion depths restrictions are limiting here. But if you don't, this is fairly elegant, and it's available for tail call optimization if that ever becomes a reality in JS.

Original (incorrect) answer

I think it's easier than what you're trying. How about this?:


const diff = (as, bs) => as.filter(a => !bs.includes(a))

const participant = ['mario', 'zelda', 'ken', 'sonic'];
const completion = ['zelda', 'ken', 'mario'];

console .log (diff (participant, completion))

Upvotes: 2

Nick
Nick

Reputation: 147256

You can use Array.findIndex to find any value in completion that is also in participant and delete it from that array. This will only delete the first occurrence of the value in participant, giving the correct result for your third example:

const solution = (participant, completion) => {
  completion.forEach(c => {
    idx = participant.findIndex(p => p == c);
    if (idx >= 0) {
      participant.splice(idx, idx + 1)
    }
  });
  return participant;
};

let participant = ['mario', 'zelda', 'ken', 'sonic'];
let completion = ['zelda', 'ken', 'mario'];

console.log(solution(participant, completion));

participant = ['mario', 'zelda', 'ken', 'sonic'];
completion = ['mario', 'ken', 'sonic'];

console.log(solution(participant, completion));

participant = ['mario', 'zelda', 'ken', 'mario'];
completion = ['mario', 'zelda', 'ken'];

console.log(solution(participant, completion));

Upvotes: 3

Related Questions