map, filter, and reduce — the three functions that replace most loops
Almost every loop that builds a new list, keeps some items and discards others, or collapses a list into one value is really just map, filter, or reduce wearing a for loop's clothing.
Beginner
2 min read
Three shapes, one underneath each common loop
A huge share of everyday loops fall into exactly three shapes: transform
every item, keep only some items, or combine every item into one result.
Functional programming gives each shape its own named, higher-order
function (a function that takes another function as an argument, from the
earlier higher-order functions lesson) instead of writing a fresh loop every
time.
map: transform every item, same number in as out
const numbers = [1, 2, 3, 4];const doubled = numbers.map(n => n * 2);// [2, 4, 6, 8]// The loop this replaces:const doubled2 = [];for (const n of numbers) { doubled2.push(n * 2);}
map always returns a new list of the same length as the input — one
output for every input, transformed by the given function. If you ever
catch yourself writing const result = [] immediately followed by a loop
that pushes exactly one transformed item per iteration, that loop is map.
filter returns a new list containing only the items where the given
function returned true — the output is the same or shorter than the
input, never longer. A loop that conditionally pushes an item, unchanged,
based on some test is filter.
reduce: collapse the whole list into one value
const numbers = [1, 2, 3, 4];const sum = numbers.reduce((total, n) => total + n, 0);// 10 — starts at 0, adds each number in turn
reduce is the most general of the three — it takes an accumulator (the
running result, total here) and combines it with each item, one at a
time, ending with a single value. Both map and filter can technically
be written using reduce alone, which is why reduce is sometimes
introduced as the "one function that can do everything" — though reaching
for the more specific map/filter when that's genuinely what you're
doing is more readable than reimplementing them with reduce every time.
Why this matters day to day
Recognizing a loop's actual shape — transform, filter, or collapse — and
reaching for the matching named function turns "here's some logic, read it
carefully to figure out what it does" into "this is a map," legible at a
glance from the function name alone. This is also exactly the mechanism
underneath SQL's SELECT (map), WHERE (filter), and SUM/COUNT
(reduce) — the same three shapes, just with different names, showing up
constantly across very different tools once you know to look for them.