Search code examples
javascriptarraysecmascript-6arrow-functionsfunction-expression

array.filter() removes <falsey> values in a function expression but not in arrow function


I'm solving a problem where a function array_diff returns values in arraya that are also in array b.

Since I've been learning about named function expressions being better for console debugging than anonymous fat arrow functions, I'm trying to solve this problem with named removeDuplicate function to filter my array.

However, I am not able to prevent the filter function from automatically removing the falsey value 0 from my returned array.

Named function expression:

function array_diff(a, b) {
  return a.filter(function removeDuplicate(x) { if(b.indexOf(x) == -1) return x; });
}

array_diff([0,1,2,3,4],[2,4]); // [1, 3]

Anonymous Fat Arrow function:

function array_diffTwo(a, b) {
  return a.filter((x) => { return b.indexOf(x) == -1 });
}

array_diffTwo([0,1,2,3,4],[2,4]); // [0, 1, 3]

Can someone explain to me why the falsey value 0 is removed in array_diff and not array_diffTwo?


Solution

  • The problem is that you return x from the filter callback. If x (the item being iterated over) is falsey, the result won't be included in the final array, even if the b.indexOf(x) == -1 test is fulfilled.

    Do the same thing you're doing with the lower code:

    return b.indexOf(x) == -1
    

    function array_diff(a, b) {
      return a.filter(function removeDuplicate(x) { return b.indexOf(x) === -1 });
    }
    
    console.log(array_diff([0,1,2,3,4],[2,4])); // [0, 1, 3]

    (as a side note, you aren't using arrow functions anywhere in the code)

    You could decrease the computational complexity from O(n ^ 2) to O(n) by creating a Set of b, instead of checking indexOfs on it on every iteration:

    function array_diff(a, b) {
      const bSet = new Set(b);
      return a.filter(function removeDuplicate(x) { return !bSet.has(x); });
    }
    
    console.log(array_diff([0,1,2,3,4],[2,4])); // [0, 1, 3]