How to Use JavaScript's Reduce
JavaScript’s reduce
function is used on each element of an array to reduce the array into a single value.
The reduce function can take in two parameters: a callback function and an optional initial value.
// Reduce works with just a callback function
const result = array.reduce(callback);
// You can also specify an initial value
const result = array.reduce(callback, initialValue);
Callback function
The callback function contains the code for how to reduce the array. It gets executed for each value in the array and takes in four arguments.
- Accumulator (required) - accumulated return value from each callback function. If an
initialValue
is provided, the accumulator equals theinitialValue
. Otherwise, it is equal to the value of the first element in the array. - Current value (required) - value of current element
- Current index (optional) - index of the current element. If an
initialValue
is provided, the current index starts at 0. Otherwise, the current index starts at 1. - Array (optional) - Array being processed in the
reduce
function
Basic reduction
We can use reduce
to sum up an array of numbers.
const numbers = [1, 2, 3, 4];
const sum = numbers.reduce(
(accumulator, currentValue) => accumulator + currentValue
);
console.log(sum); // 10
The example above uses ES6
arrow functions. In ES5
, this can be written as:
let sum = numbers.reduce(function(accumulator, currentValue) {
return accumulator + currentValue;
});
If you want to learn more about why the arrow function doesn’t need an explicit return like it does in ES5
please check out this tutorial on return values.
Breakdown of callback function
The reduce
function takes in two arguments: callback and initialValue. In the sum reduction, there is no initialValue
so we will focus only on how the callback function works.
The callback function is (accumulator, currentValue) => accumulator + currentValue
and contains the accumulator
and currentValue
arguments.
Because there is no initialValue
the accumulator
will equal to the first value of the array, i.e. 1. The currentValue
is the next number in the array, i.e. 2.
The two values are added together and then the sum of those two numbers are returned to be used as the accumulator
. The accumulator
is now equal to the sum of 3 and the currentValue
is 3.
This process continues until the end of the array is reached.
// Process of reducing the array of numbers
accumulator + currentValue = newAccumulator
1 + 2 = 3
3 + 3 = 6
6 + 4 = 10
Introduction of an initialValue
How would this be different if there were an initialValue of 10?
const numbers = [1, 2, 3, 4];
const initialValue = 10;
const sum = numbers.reduce(
(accumulator, currentValue) => accumulator + currentValue,
initialValue
);
console.log(sum); // 20
When there was no initialValue
, the accumulator
was first set to 1 and currentValue
was 2. However, now the accumulator
is set to 10 and the currentValue
is 1.
// Process of reducing the array of numbers with an initialValue
initialValue + currentValue = accumulator
accumulator + currentValue = newAccumulator
10 + 1 = 11
11 + 2 = 13
13 + 3 = 16
16 + 4 = 20
Mathemetical operations
You can do more than just add the numbers. Try what will happen if you replace accumulator + currentValue
with any other operation.
const numbers = [1, 2, 3, 4];
const initialValue = 5;
const product = numbers.reduce(
(accumulator, currentValue) => accumulator * currentValue
);
const exponential = numbers.reduce(
(accumulator, currentValue) => accumulator ** currentValue,
initialValue
);
Reduction with array of objects
The reduce
function can be used for data types in addition to numbers.
Let’s say you run an online shop. When the shopper views her cart, she wants to see the total cost of the items.
Each item’s information is represented by an object with the item’s id, name, quantity, and unit price.
const shoppingCart = [
{ id: 1, name: 'balloon', quantity: 4, unitPrice: 2.25 },
{ id: 2, name: 'plate', quantity: 10, unitPrice: 0.35 },
{ id: 3, name: 'cup', quantity: 6, unitPrice: 0.25 },
];
The callback function loops through each element of the array. To get the subtotal for each item we would do quantity * unitPrice
. The element is an object and you can use its keys to get the values you need. Therefore, you would do currentValue.quantity * currentValue.unitPrice
to get the subtotal.
const shoppingCart = [
{ id: 1, name: 'balloon', quantity: 4, unitPrice: 2.25 },
{ id: 2, name: 'plate', quantity: 10, unitPrice: 0.35 },
{ id: 3, name: 'cup', quantity: 6, unitPrice: 0.25 },
];
const total = shoppingCart.reduce(
(accumulator, currentValue) =>
accumulator + currentValue.quantity * currentValue.unitPrice
);
console.log(total); // '[object Object]3.51.5'
We’re taking the accumulator and adding it to each item’s subtotal, but the answer is not what we expected. Why doesn’t this reduction return the total as a number?
Use case for initialValue
We learned previously, if the there is no initial value declared then the first element of the array becomes the accumulator.
Without an initialValue, the function started with {id: 1, name: 'balloon', quantity: 4, unitPrice: 2.25}
as the accumulator
and continued to add values to this object.
accumulator + currentValue.quantity * currentValue.unitPrice = newAccumulator
// First adds the subtotal (number) to an object, resulting in a string
{id: 1, name: 'balloon', quantity: 4, unitPrice: 2.25} + 10 * 0.35 = '[object Object]3.5'
// Then adds the subtotal (number) to a string, resulting in a string
'[object Object]3.5' + 6 * 0.25 = '[object Object]3.51.5'
Including an initialValue
of 0 will now return the correct result.
const total = shoppingCart.reduce(
(accumulator, currentValue) =>
accumulator + currentValue.quantity * currentValue.unitPrice,
0
);
console.log(total); // 14
Powerful use for reduce
Reduce allows you to manipulate arrays in an endless number ways. One of my favorite uses for reduce is to change the array into an object.
This is useful for the times when I get data from an API endpoint and I want to get the value of a field without looping through the data each time.
Reducing an array into an object eliminates the need to traverse through the array and instead you can do object[key]
to get whatever values you are searching for. Read about how to turn an array into an object.