Most often we perform filter
followed by map
and it turns out that combining both in one function would certainly avoid multiple iteration.
Array.prototype.filterMap = function(filter) {
const r = [];
for(let i=0; i<this.length; i++) {
const item = filter(this[i], i, this);
if (item !== undefined) {
r.push(item);
}
}
return r;
};
// usage..
emails = customers.filterMap(
(c) => c.active ?
{ name: c.name, email: c.email } :
undefined);
// as opposed to
emails = customers.filter( (c) => c.active)
.map( (c) => ({ name: c.name, email: c.email }));
Ideally we can change behavior of Array.map
to adapt Array.filterMap
but we don't know what impact it will have on numerous libraries.
Top comments (11)
If I were to implement something like
filterMap
, I would pass in the predicate and the transformation as separate functions. However, you can usereduce
for what you're doing, no need to implement a new method onArray
.It is 80% slower, jsperf.com/array-filtermap/2
Yeah, sorry, been using array destructuring too much lately. If it's speed we're going after we can't create a new array at each iteration step.
This way reduce can be used as map as well, nice trick but I still prefer filterMap for its smaller syntax.
The same exact logic but written with reduce instead of a for loop.
more info: Map, Filter, Reduce vs For Loops (syntax)
Also while this function is very cleaver, it is now considered an anti-pattern to modify the prototype of built in objects.
We want to avoid any "smoosh gate" fiasco in the future.
Well we can have an independent function with array being first parameter. I really don’t care about anti pattern because extending prototype is the best feature of JS. Otherwise everything is possible in other languages
That is what I would recommend
But see, you should. Something seemingly harmless as extending a prototype has cause much difficulty in the JavaScript community due to name collisions.
An older but popular library extended Array to include
flatten
. The problem was this version conflicted with the implementation proposed by the TC39. Because the TC39 could not use flatten without breaking the internet, the dumb namesmoosh
was recommended. github.com/tc39/proposal-flatMap/p...This has happened multiple times.
Today the TC39 is currently arguing over a name for a global context object. Because node has called their global object
global
, this name cannot be used without breaking the internet again. So they are currently proposing the horrible name ofglobalThis
github.com/tc39/proposal-global/is...While your code may have little impact now. It could have very large effects in the future.
So you should definitely care.
Cheers!
Yes you got that right !!
There is the flatMap method that does exactly that filter + map :)
this method not only lets you dynamically filter the array, but it also gives the ability to add elements to the array dynamically.
developer.mozilla.org/en-US/docs/W...
Ideally, filterMap shouldn't restrict me from mapping my elements into anything I could map it to. Including
undefined
.This would be a better Api, really similar to a separate filter and map, but with one loop inside.