javascriptnode.jsfunctional-programming

filter and map in same iteration


I have this simple situation where I want to filter and map to the same value, like so:

 const files = results.filter(function(r){
      return r.file;
    })
    .map(function(r){
       return r.file;
    });

To save lines of code, as well as increase performance, I am looking for:

const files = results.filterAndMap(function(r){
  return r.file;
});

does this exist, or should I write something myself? I have wanted such functionality in a few places, just never bothered to look into it before.


Solution

  • If you really need to do it in 1 function, you'll need to use reduce like this

    results.reduce(
      // add the file name to accumulator if it exists
      (acc, result) => result.file ? acc.concat([result.file]) : acc,
      // pass empty array for initial accumulator value
      []
    )
    

    And if you need to squeeze more performance you can change concat to push and return the original accumulator array to avoid creating extra arrays.

    However, the fastest solution is probably a good old for loop which avoids all the function calls and stack frames

    files = []
    for (var i = 0; i < results.length; i++) {
      var file = results[i].file
      if (file) files.push(file)
    }
    

    But I think filter/map approach is much more expressive and readable