reduce()
The JavaScript reduce()
method runs a function on each element of the array from left to right (first to last), resulting in a single (reduced to) value.
Making it a good choice for calculating totals, accumulating values, or transforming arrays into different data structures.
The reduceRight()
method is also available for processing an array from right to left.
Syntax
const result = array.reduce(function(accumulator, currentValue, index, array) {
// return accumulated value
}, initialValue);
Parameters:
- function: Function to run on each element of the array, taking four possible arguments:
- accumulator: The current total (accumulated) value, returned by the previous callback function call.
- currentValue: The current array element being processed.
- index (optional): The index position of the current array element.
- array (optional): The original array the
reduce()
method was called upon.
- initialValue (optional): An initial starting value for the accumulator.
Basic usage
Let's start with a simple example of calculating the total price of pizza orders:
const orders = [
{ name: 'Margherita', price: 10 },
{ name: 'Pepperoni', price: 13 },
{ name: 'Supreme', price: 15 }
];
const totalPrice = orders.reduce((total, pizza) => {
return total + pizza.price;
}, 0);
console.log(totalPrice);
// Output: 38
In this example, the total
is the accumulated value. We do this in the return
statement by adding the pizza.price
to the current total
for each array value.
Using the index parameter
The index parameter can be useful for tracking progress or creating numbered lists:
const pizzaToppings = ['Cheese', 'Pepperoni', 'Mushrooms', 'Olives'];
const numberedList = pizzaToppings.reduce((list, topping, index) => {
return list + `${index + 1}. ${topping}\n`;
}, '');
console.log(numberedList);
// Output:
// 1. Cheese
// 2. Pepperoni
// 3. Mushrooms
// 4. Olives
Using the array parameter
The array parameter provides reference to the original array:
const pizzaOrders = [
{ name: 'Margherita', price: 10, quantity: 2 },
{ name: 'Pepperoni', price: 12, quantity: 1 },
{ name: 'Supreme', price: 15, quantity: 3 }
];
const orderSummary = pizzaOrders.reduce((summary, order, index, array) => {
const isLast = index === array.length - 1;
return summary + `${order.name} (${order.quantity}x)${isLast ? '' : ', '}`;
}, 'Order Summary: ');
console.log(orderSummary);
// Output: Order Summary: Margherita (2x), Pepperoni (1x), Supreme (3x)
This example checks the length of the original array, and stores it into the isLast
variable. This is then used to only add a comma when the item is not the last one in the list.
Working with objects in arrays
The reduce()
method is also useful when working with arrays of objects:
const pizzaMenu = [
{ name: 'Margherita', price: 10, category: 'Standard' },
{ name: 'Pepperoni', price: 12, category: 'Standard' },
{ name: 'Supreme', price: 15, category: 'Specialty' },
{ name: 'Meat feast', price: 13, category: 'Specialty' }
];
// Group pizzas by category
const menuByCategory = pizzaMenu.reduce((categories, pizza) => {
if (!categories[pizza.category]) {
categories[pizza.category] = [];
}
categories[pizza.category].push(pizza);
return categories;
}, {});
console.log(menuByCategory);
/* Output:
{
"Standard": [
{
"name": "Margherita",
"price": 10,
"category": "Standard"
},
{
"name": "Pepperoni",
"price": 12,
"category": "Standard"
}
],
"Specialty": [
{
"name": "Supreme",
"price": 15,
"category": "Specialty"
},
{
"name": "Meat feast",
"price": 13,
"category": "Specialty"
}
]
}
*/
Chaining reduce()
The reduce()
method can be combined with other array methods for powerful data transformations:
const pizzaOrders = [
{ name: 'Margherita', price: 10, quantity: 2 },
{ name: 'Pepperoni', price: 12, quantity: 1 },
{ name: 'Supreme', price: 15, quantity: 3 }
];
// Calculate total value of orders over $20
const highValueOrders = pizzaOrders
.filter(order => order.price * order.quantity > 20)
.reduce((total, order) => total + (order.price * order.quantity), 0);
console.log(highValueOrders);
// Output: 45 (Supreme: 15 * 3 = 45)
Nesting the reduce() method
When working with nested data, reduce()
can be used at multiple levels:
const pizzaStores = [
{
name: "Store 1",
orders: [
{ pizza: "Margherita", quantity: 2 },
{ pizza: "Pepperoni", quantity: 1 }
]
},
{
name: "Store 2",
orders: [
{ pizza: "Margherita", quantity: 1 },
{ pizza: "Supreme", quantity: 3 }
]
}
];
// Calculate total pizzas sold across all stores
const totalPizzasSold = pizzaStores.reduce((total, store) => {
const storeTotal = store.orders.reduce((storeSum, order) => {
return storeSum + order.quantity;
}, 0);
return total + storeTotal;
}, 0);
console.log(totalPizzasSold);
// Output: 7
Practical example: creating a progress bar
const progress = [1, 2, 3, 4, 5];
const progressBar = progress.reduce((bar, step, index, array) => {
const position = index + 1;
const completed = '■'.repeat(position);
const remaining = '□'.repeat(array.length - position);
return bar + `Step ${position}/5: ${completed}${remaining}\n`;
}, 'Progress:\n');
console.log(progressBar);
Practical example: creating a price summary
const pizzaOrders = [
{ name: 'Margherita', price: 10, quantity: 2 },
{ name: 'Pepperoni', price: 12, quantity: 5 },
{ name: 'Supreme', price: 15, quantity: 3 }
];
const orderSummary = pizzaOrders.reduce((summary, order) => {
const itemTotal = order.price * order.quantity;
return {
items: summary.items + order.quantity,
subtotal: summary.subtotal + itemTotal,
tax: summary.tax + (itemTotal * 0.2), // 20% tax
itemsList: [...summary.itemsList, `${order.name} (${order.quantity}x)`]
};
}, { items: 0, subtotal: 0, tax: 0, itemsList: [] });
const total = orderSummary.subtotal + orderSummary.tax;
console.log({
...orderSummary,
total: Math.round(total * 100) / 100
});
/* Output:
{
"items": 10,
"subtotal": 125,
"tax": 25,
"itemsList": [
"Margherita (2x)",
"Pepperoni (5x)",
"Supreme (3x)"
],
"total": 150
}
*/
When to use reduce()
vs. other methods
Use reduce()
when:
- You require transforms like aggregating, grouping, or counting data.
- You need to transform an array into a single value.
- You want to perform calculations on each element and maintain a running total.
Consider using other methods when:
- You need to process the array elements from right to left, (use
reduceRight()
). - You need to find an element (use
find()
orfindIndex()
). - You simply want a new array with transformed elements (use
map()
). - You just want to filter elements based on a condition (use
filter()
). - You only need to know if elements meet a condition (use
some()
orevery()
). - You want to perform an action for each element without accumulating a result (use
forEach()
).
Conclusion
The reduce()
method is a powerful JavaScript array method, providing a way to process arrays and transform the data into any type of value. It's particularly useful for aggregating data and transforming values into a single result. While it has a steeper learning curve than many other array methods, reduce()
can be a very useful method to learn.