reduce
map and filter return an array, while a sum, a maximum or a count is a single value. For such tasks the conveyor needs a piggy bank, not a second belt.
Picture a worker with a piggy bank by the belt. Before starting, the worker puts a starting sum into the piggy bank, say zero. The worker opens each box that arrives, adds what is inside to the money from the piggy bank and puts it all back. When the belt is empty, the piggy bank holds the total.
The reduce method works the same way: it walks the array and combines all the elements into one value.
const nums = [4, 7, 10];
const sum = nums.reduce((total, n) => total + n, 0);
console.log(sum); // 21Let's take the call apart:
(total, n) => total + nis the callback, our worker: it takes the money from the piggy banktotaland the next boxn.0is the starting sum in the piggy bank.reducereturns what is in the piggy bank at the end, and the program prints21.
Interviewers often ask you to sum an array with reduce. This example is the answer.
The accumulator
reduce takes two arguments: a callback and an initial value, here 0. The callback gets the running result and the next element, and returns the new running result. The running result is called the accumulator; in the example it is the parameter total.
The callback's parameter names are up to you: total and n tell the reader what each one holds.
How the calls go
The accumulator passes from call to call by three rules:
- On the first call the accumulator equals the initial value.
- Each next call gets what the previous one returned.
- Whatever the last call returns is what
reducereturns.
For [4, 7, 10] the calls go like this:
total | n | the callback returns |
|---|---|---|
0 | 4 | 4 |
4 | 7 | 11 |
11 | 10 | 21 |
Press "Next step" and watch total: each new call of add gets the number the previous one returned. The callback in the widget's program is the named function add, so that each of its calls has a frame of its own. Between the script and add frames lies the frame of reduce itself: the method is a function too, it keeps the accumulator and calls add for each element itself.
1const nums = [4, 7, 10];2 3function add(total, n) {4 const next = total + n;5 return next;6}7 8const sum = nums.reduce(add, 0);9console.log(sum);
The script calls reduce and passes it the callback add and the initial value 0.
The initial value must not spoil the result: for a sum it is 0, for a product 1. reduce does not change the original array.
Not only a sum
Here the piggy bank analogy ends. A piggy bank holds only money, while the accumulator can hold any value: a maximum, a counter, a string.
Maximum
To find the maximum, the callback compares the element with the best one so far and returns the larger one. Here the initial value is the first element.
const temps = [12, 31, 18];
const max = temps.reduce((best, t) => (t > best ? t : best), temps[0]);
console.log(max); // 31The number 0 does not fit a maximum. With only negative numbers the result is 0, which is not in the array.
Counter
The accumulator can also be a counter. The call words.reduce((count, w) => (w.length > 3 ? count + 1 : count), 0) counts the words longer than three letters. Here the callback returns either the increased counter or the old one.
Without an initial value
The initial value can be left out. Then the first element becomes the accumulator, and the callback starts from the second one: nums.reduce((total, n) => total + n) also gives 21.
Common mistake
No initial value is passed, and the array turns out to be empty:
const empty = [];
const total = empty.reduce((sum, n) => sum + n); // ✗TypeError: Reduce of empty array with no initial valueWithout an initial value, reduce takes the accumulator from the first element, and an empty array has none. Pass an initial value: empty.reduce((sum, n) => sum + n, 0) returns 0, and the callback is never called. With an initial value, reduce works with an array of any length.
Key points
reducecombines all the elements of an array into one value, the accumulator.- The first call of the callback gets the initial value, each next one what the previous one returned.
reducereturns the result of the last call and does not change the original array.- Without an initial value,
reduceon an empty array stops the program with aTypeError.
Subscribe to take the course
The course is free. Sign in with Telegram and subscribe to the channel to open every lesson.