DEV Community

Discussion on: Of a Higher Order - Map, Filter, Reduce

Collapse
 
curtisfenner profile image
Curtis Fenner • Edited

The post hints at it, but reduce is actually much more powerful than the other two. Reduce acts on structures a bit more powerful than monoids. The things that it "eats" don't have to be the same type as the things it produces. (I'm not sure if this kind of operation has a name)

This generality lets you write filter and map in terms of reduce (not a good idea, neither in terms of readability nor performance, but cool!):

list.map(f) can be written list.reduce((a, b) => [...a, f(b)], []).

list.filter(f) can be written list.reduce((a, b) => [...a, ...(f(b) ? [b] : [])], [])

For both, the "identity" is [], which makes sense since that's the result of filtering or mapping on an empty array. The operations are actually quite simple, though a bit dense to read.

In turn, both of these are both instantiations of flatmap, a version of map where the result of the function applied is a list, and all of the resulting lists are joined together:

flatmap = (list, f) => list.reduce((a, b) => [...a, ...f(b)], [])

then map = (list, f) => flatmap(list, x => [f(x)]) and filter = (list, f) => flatmap(list, x => f(x) ? [x] : []).