Understanding the Reduce Method
The reduce() method is one of JavaScript’s most powerful array methods. It executes a reducer function on each element of an array, resulting in a single output value. Unlike map() which returns a new array, reduce() returns a single accumulated value.
Key Point: The reduce() method is perfect for operations that need to combine array elements into a single result, such as summing values, flattening arrays, or calculating averages.
Reduce Method Syntax
Basic Syntax
const result = array.reduce(function(accumulator, currentValue, index, array) {
// return updated accumulator
}, initialValue);
- accumulator: Accumulates the callback’s return values
- currentValue: The current element being processed
- index: The index of the current element (optional)
- array: The array being traversed (optional)
- initialValue: Value to use as the first accumulator (optional)
Basic Reduce Examples
Summing Array Elements
const numbers = [2, 4, 6, 8];
// Without initial value
const sum = numbers.reduce(function(acc, curr) {
return acc + curr;
});
console.log(sum); // 20
// With initial value
const sumWithInitial = numbers.reduce(function(acc, curr) {
return acc + curr;
}, 10);
console.log(sumWithInitial); // 30 (10 + 2 + 4 + 6 + 8)
// Using arrow function
const sumArrow = numbers.reduce((acc, curr) => acc + curr, 0);
console.log(sumArrow); // 20
Calculating Product
const numbers = [2, 3, 4, 5];
// Calculate product
const product = numbers.reduce((acc, curr) => acc * curr, 1);
console.log(product); // 120 (2 * 3 * 4 * 5)
Flattening Arrays with Reduce
One of the most common uses of reduce() is to flatten multidimensional arrays into a single-dimensional array.
Flattening a 2D Array
const twoDArray = [[1, 2], [3, 4], [5, 6]];
// Flatten using reduce
const flatArray = twoDArray.reduce((acc, curr) => {
return acc.concat(curr);
}, []);
console.log(flatArray); // [1, 2, 3, 4, 5, 6]
// Using spread operator (more concise)
const flatArraySpread = twoDArray.reduce((acc, curr) => [...acc, ...curr], []);
console.log(flatArraySpread); // [1, 2, 3, 4, 5, 6]
Flattening Arrays with Mixed Depths
const mixedArray = [1, [2, 3], [4, [5, 6]], 7];
// Flatten one level
const flatOneLevel = mixedArray.reduce((acc, curr) => acc.concat(curr), []);
console.log(flatOneLevel); // [1, 2, 3, 4, [5, 6], 7]
// Recursive flattening function
function flattenDeep(arr) {
return arr.reduce((acc, curr) => {
return Array.isArray(curr) ? acc.concat(flattenDeep(curr)) : acc.concat(curr);
}, []);
}
const completelyFlat = flattenDeep(mixedArray);
console.log(completelyFlat); // [1, 2, 3, 4, 5, 6, 7]
Working with Object Arrays
Summing Object Properties
const employees = [
{ name: "John", salary: 50000 },
{ name: "Jane", salary: 60000 },
{ name: "Bob", salary: 55000 }
];
// Calculate total salaries
const totalSalary = employees.reduce((acc, curr) => {
return acc + curr.salary;
}, 0);
console.log(totalSalary); // 165000
// Calculate average salary
const averageSalary = employees.reduce((acc, curr, index, array) => {
acc += curr.salary;
return index === array.length - 1 ? acc / array.length : acc;
}, 0);
console.log(averageSalary); // 55000
Reduce vs ReduceRight
Reduce vs ReduceRight Comparison
| Feature | reduce() | reduceRight() |
|---|---|---|
| Direction | Left to right | Right to left |
| Starting point | First element | Last element |
| Use case | Most common operations | Right-associative operations |
ReduceRight Example
const numbers = [2, 3, 4];
// Exponentiation: 2^(3^4)
const resultRight = numbers.reduceRight((acc, curr) => Math.pow(curr, acc));
console.log(resultRight); // 2.4178516392292583e+24
// Compare with regular reduce: (2^3)^4
const resultLeft = numbers.reduce((acc, curr) => Math.pow(acc, curr));
console.log(resultLeft); // 4096
Common Questions Answered
Finding Maximum Value
const numbers = [12, 45, 7, 32, 89, 23];
// Find maximum value
const max = numbers.reduce((acc, curr) => {
return curr > acc ? curr : acc;
}, numbers[0]);
console.log(max); // 89
Grouping Objects by Property
const people = [
{ name: "Alice", age: 25 },
{ name: "Bob", age: 30 },
{ name: "Charlie", age: 25 },
{ name: "David", age: 30 }
];
// Group by age
const groupedByAge = people.reduce((acc, curr) => {
const age = curr.age;
if (!acc[age]) {
acc[age] = [];
}
acc[age].push(curr);
return acc;
}, {});
console.log(groupedByAge);
// {
// 25: [{ name: "Alice", age: 25 }, { name: "Charlie", age: 25 }],
// 30: [{ name: "Bob", age: 30 }, { name: "David", age: 30 }]
// }
Best Practices
- Always provide an initial value for predictable results
- Use descriptive variable names for accumulator and currentValue
- Consider using the spread operator for array concatenation
- For complex transformations, break the logic into separate functions
- Remember that reduceRight processes arrays from right to left