reduce
description
Returns an output value after combining an input collection's values using the provided reducer function. It works very similarly to Array.prototype.reduce
, excepts it also works on Objects, Sets, and Maps. It also accepts an asynchronous reducer.
The reducer function should have the following signature (Any accumulator, Any value, Any key, Collection collection) => Any
where:
accumulator
is the the result of calling the reducer successively on the previous items of the input collectionvalue
is the value of the current itemkey
is the key of the current itemcollection
is the input collection
The seed
parameter is used as the value for accumulator
on the reducer's
first call.
Contrary to Array.prototype.reduce
, the seed
parameter is not optional.
If the reducer is asynchronous, the result will be a Promise
. Use Promise.prototype.then
or the await
keyword to retrieve its inner value.
reduce
processes its calls to the reducer in series, because each of this call requires an up-to-date version of the accumulator
.
If you find yourself in a situation where you want the calls to be made in parallel, you can compose map and reduce to achieve the desired result: compose(reduce(syncReducer), map(asyncMapper))
.
example
basic example
Here, we simply want to sum an array of numbers, so we define our reducer, sum, which will add the current item's value of the result of the previous iterations.
Internally, sum will be called with the following parameters
sum(0, 3) // 3
0 is theseed
value, and 3 is the value of the array's first itemsum(3, 1) // 4
The result of the previous iterations is 3, and the value of the array's second item is 4sum(4, 4) // 8
Theaccumulator
's value is now 4, and we want to add 4 to it. The iteration is done.
The final result is 8.
reducing other data structures
reduce
also works on Objects
, Sets
and Maps
.
using an asynchronous reducer
Let's say we have an array of starships, and want to know their total combined cargo capacity. Since the data is not locally available, we need to retrieve it from the Star Wars API. Our fetchCapacity
utility function will simply fetch a starship's data from its id and return its capacity. Since it needs to make an HTTP request, it's obviously asynchronous. Then, we can define sumCapacity
, which will be our reducer, and whose task will be to fetch the current starship's capacity and add it to the accumulator. Because our reducer is asynchronous, we need to use the await keyword to wait until all the underlying Promises are resolved.
optimizing the previous example
In our previous example, our reducer is asynchronous because we need to make an HTTP request to retrieve each starship's data. However, since our real reducing operation is simply an addition, which is a commutative operation, we could make the HTTP requests in parallel and add the capacities synchronously after all the remote data has been fetched.
To do so, we can compose map, which will make the HTTP requests in parallel, and reduce, which will sum the capacities. map(fetchCapacity)
returns an array of capacities, which reduce(sumCapacity, 0)
, used in a partially applied form, will accept as the input collection. The mapping operation is asynchronous, while the summing operation is synchronous. The composition of the two operations is asynchronous, which is why we must use the await
keyword to retrieve the end result.
Last updated