Step 1 of 7 · Reading · ~3 min
Learn
Collections
Map, Filter, Reduce
Three array methods replace most hand-written loops over data. By the end of this lesson you can transform a list with map, select from it with filter, collapse it to one value with reduce, and chain them into a pipeline.
All three take a callback: a function you hand over, which the method calls for you on each item. None of them changes the array they are called on; each returns a new value.
map: one result per item
The callback runs once per item and its return value becomes the matching item of the new array. The result is always the same length as the original. The callback may also receive the index as a second argument: prices.map((p, i) => i + ": " + p).
filter: keep the items that pass
The callback returns true (keep) or false (drop). The result is shorter, or equal in length, and can be empty.
reduce: many items into one value
The callback receives the accumulator (what has been built so far) and the current item, and returns the new accumulator. The second argument of reduce, 0, is the accumulator's starting value. Trace it:
| step | sum before | item | returned |
|---|---|---|---|
| 1 | 0 | 4 | 4 |
| 2 | 4 | 10 | 14 |
| 3 | 14 | 25 | 39 |
Always pass the starting value. Without it, reduce starts from the first item, and on an empty array it throws a TypeError. With it, an empty array simply returns the starting value.
reduce can build things other than numbers: start with "" to build a string, or [] to build a list.
Pipelines
Each method returns an array (except reduce, which returns whatever the accumulator is), so they chain, top to bottom:
Read it as a sentence: "from the cart, keep prices of at least 4, take 1 off each, and add them up". Putting filter before map is usually cheaper and clearer, since you transform only what you keep. If the chain stops being readable, break it into named steps with const.
Related helpers
forEach(cb) runs a callback for each item and returns nothing (use it for side effects like printing). find(cb) returns the first item that passes, or undefined. some(cb) and every(cb) answer "does any / do all pass". flat() and flatMap(cb) flatten one level of nested arrays.
Common mistakes
- Using
mapto loop for side effects, then ignoring the new array. UseforEachorfor...of. - Writing a
maporfiltercallback with braces and noreturn:p => { p * 2 }gives an array ofundefined. - Omitting the starting value of
reduceand crashing on an empty array. - Forgetting the callback of
reducemust return the accumulator. - Dividing by
list.lengthwhen the list may be empty; check for that case first.
Your exercise
Build a pipeline over name:score tokens. Convert, filter, then reduce, and treat the case where nothing passes. The starter splits the line into tokens and leaves the rest to you.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…