Mastering Array.reduce()
HardArray.reduce() is the most powerful and versatile array method. It transforms an array into any value type: number, string, object, array, or even another function. Mastering reduce patterns is essential for functional programming and many interview problems. This concept covers common patterns: sum, groupBy, flatten, pipe, and count.
Interactive Visualization
mutation Methods
1
2
3
Key Points
- reduce((accumulator, current) => newAccumulator, initialValue)
- Can transform array into any type (number, object, array, etc.)
- Always provide initial value to avoid bugs
- Common patterns: sum, groupBy, flatten, pipe, count
- Can replace map+filter chains for single pass
- More powerful but less readable than specialized methods
Code Examples
Sum and Product
const nums = [1, 2, 3, 4, 5]; // Sum const sum = nums.reduce((acc, n) => acc + n, 0); console.log(sum); // 15 // Product const product = nums.reduce((acc, n) => acc * n, 1); console.log(product); // 120 // Maximum const max = nums.reduce((acc, n) => n > acc ? n : acc, -Infinity); console.log(max); // 5 // Initial value is crucial!
Basic reduce patterns. Always provide initial value.
groupBy Pattern
const users = [ { name: 'Alice', city: 'NYC' }, { name: 'Bob', city: 'LA' }, { name: 'Carol', city: 'NYC' } ]; // Group by city const grouped = users.reduce((acc, user) => { const key = user.city; if (!acc[key]) { acc[key] = []; } acc[key].push(user); return acc; }, {}); console.log(grouped); // { // NYC: [{ name: 'Alice', city: 'NYC' }, { name: 'Carol', city: 'NYC' }], // LA: [{ name: 'Bob', city: 'LA' }] // }
Most common reduce pattern: group array elements by a key.
Flatten Array
const nested = [[1, 2], [3, 4], [5, 6]]; // Flatten one level const flat = nested.reduce((acc, arr) => acc.concat(arr), []); console.log(flat); // [1, 2, 3, 4, 5, 6] // Or with spread const flat2 = nested.reduce((acc, arr) => [...acc, ...arr], []); // Deep flatten (recursive) const deepNested = [1, [2, [3, 4]], 5]; function deepFlatten(arr) { return arr.reduce((acc, val) => acc.concat(Array.isArray(val) ? deepFlatten(val) : val), [] ); } console.log(deepFlatten(deepNested)); // [1, 2, 3, 4, 5]
Flatten nested arrays. For simple cases, use arr.flat() instead.
Count Occurrences
const fruits = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple']; // Count each fruit const counts = fruits.reduce((acc, fruit) => { acc[fruit] = (acc[fruit] || 0) + 1; return acc; }, {}); console.log(counts); // { apple: 3, banana: 2, orange: 1 } // With nullish coalescing const counts2 = fruits.reduce((acc, fruit) => { acc[fruit] = (acc[fruit] ?? 0) + 1; return acc; }, {});
Count frequency of elements. Very common interview pattern.
Pipeline (Function Composition)
// Compose functions left to right const pipe = (...fns) => x => fns.reduce((v, f) => f(v), x); // Usage const add5 = x => x + 5; const multiply2 = x => x * 2; const toString = x => String(x); const transform = pipe(add5, multiply2, toString); console.log(transform(3)); // "16" // (3 + 5) * 2 = 16 -> "16" // Equivalent to: toString(multiply2(add5(3)))
Advanced: use reduce for function composition and pipelines.
Common Mistakes
- Forgetting initial value (causes TypeError on empty array)
- Not returning accumulator in callback
- Using reduce when map/filter/find would be clearer
- Mutating the accumulator object incorrectly
Interview Tips
- Always provide initial value
- Know common patterns: sum, groupBy, flatten, count
- Be able to implement groupBy from scratch
- Understand reduce can create any data type