Search code examples
javascriptarraysbuilt-in

Javascript: Pass include method to filter array


Filtering arrays in Javascript is possible by passing a custom function to the filter method:

const bigArray = [1, 2, 3, 4, 5, 6, 7, 8, 9];
const filteredArray = bigArray.filter(item => item < 5);

It's also possible to pass the function as a "reference":

function largerThanFive(item) {
  return item => item < 5;
}

const bigArray = [1, 2, 3, 4, 5, 6, 7, 8, 9];
const filteredArray = bigArray.filter(largerThanFive);

I tried to use this to intersect two arrays via:

const bigArray = [1, 2, 3, 4, 5, 6, 7, 8, 9];
const smallArray = [0, 1, 2];
const filteredArray = bigArray.filter(smallArray.includes);

But I get the error: TypeError: Cannot convert undefined or null to object

I don't understand why. Can someone elaborate on that?


Solution

  • By using a prototype function, you are loosing the reference to the object smallArray. In this case you need either to bind the object with Function#bind,

    const bigArray = [1, 2, 3, 4, 5, 6, 7, 8, 9];
    const smallArray = [0, 1, 2];
    const filteredArray = bigArray.filter(Array.prototype.includes.bind(smallArray));
    
    console.log(filteredArray);

    or use thisArg parameter of Array#filter.

    const bigArray = [1, 2, 3, 4, 5, 6, 7, 8, 9];
    const smallArray = [2, 1, 0];
    const filteredArray = bigArray.filter(Array.prototype.includes, smallArray);
    
    console.log(filteredArray); // 2 is missing

    But both above approaches do not work, because Array#includes uses a second parameter fromIndex, which is handed over from the calling function as index and omits values to be checked whoes indices are smaller.

    As result, you need a function which supports the same function signature as the api of the methods supplies or which is smaller as the callback is using.

    For example a working approach would be to use a Set as thisArg along with Set#has as callback. This method uses only one parameter, which fits perfectly.

    const bigArray = [1, 2, 3, 4, 5, 6, 7, 8, 9];
    const smallArray = [2, 1, 0];
    const filteredArray = bigArray.filter(Set.prototype.has, new Set(smallArray));
    
    console.log(filteredArray);