Difference between map, filter, and reduce
Advertisement
🧩 Scenario
Architecture Walkthrough
map: Transform Every Element
map creates a new array by applying a callback to every element of the source array. The callback receives the current element, its index, and the original array. Whatever the callback returns becomes the corresponding element in the new array. The original array is not modified.
If the callback does not explicitly return a value, it implicitly returns undefined, so the resulting array will be filled with undefined. This is one of the most common beginner bugs with map. A concise arrow function without curly braces returns implicitly, but adding braces requires an explicit return.
filter: Select Matching Elements
filter creates a new array containing only elements for which the callback returns a truthy value. Elements for which the callback returns a falsy value are excluded. The original array is not modified and the length of the result may be shorter.
filter is useful when combined with map: filtering first reduces the array size before the transformation step, which can improve performance if the transformation is expensive. However, if the filter condition depends on the transformed value, the order must be reversed.
reduce: Accumulate to a Single Value
reduce is the most general of the three methods. It applies a callback to an accumulator and each element in turn, returning a single final value. The accumulator starts as the second argument to reduce (the initial value). The callback receives the current accumulator, the current element, the index, and the original array.
reduce can produce any output: a number, a string, an object, or even a new array. This makes it powerful enough to implement both map and filter internally. In practice, use reduce for aggregations (sum, count, average), grouping (an array of items into an object keyed by category), and any transformation that produces a different shape than the input.
Key Code Explained
const orders = [
{ id: 1, status: 'shipped', total: 120 },
{ id: 2, status: 'pending', total: 85 },
{ id: 3, status: 'shipped', total: 200 },
{ id: 4, status: 'pending', total: 45 },
];
// map: transform to a new shape
const totals = orders.map((o) => o.total);
// [120, 85, 200, 45]
// filter: select by condition
const shipped = orders.filter((o) => o.status === 'shipped');
// [{ id: 1, ... }, { id: 3, ... }]
// reduce: sum all totals
const grandTotal = orders.reduce((sum, o) => sum + o.total, 0);
// 450
// reduce: group by status (a non-obvious but practical use)
const grouped = orders.reduce((acc, order) => {
const key = order.status;
if (!acc[key]) acc[key] = [];
acc[key].push(order);
return acc;
}, {});
// { shipped: [order1, order3], pending: [order2, order4] }
// Chained: sum of totals for shipped orders only
const shippedTotal = orders
.filter((o) => o.status === 'shipped')
.reduce((sum, o) => sum + o.total, 0);
// 320
// Common mistake: missing return in map with curly braces
const broken = orders.map((o) => {
o.total * 1.1; // no return — produces [undefined, undefined, ...]
});
const correct = orders.map((o) => ({
...o,
total: o.total * 1.1,
}));
The grouping reduce example is worth memorizing for interviews because it shows reduce being used to produce an object from an array, not just a scalar value. This pattern comes up in data processing frequently.
Tradeoffs
| Method | Returns | Use when |
|---|---|---|
| map | New array, same length | You need to transform every element into a new value |
| filter | New array, shorter or equal length | You need to select a subset of elements |
| reduce | Single value of any type | You need to aggregate, group, or fold an array into one result |
| forEach | undefined | You only need side effects and do not care about a return value |
What Interviewers Actually Check
- Whether you can explain each method's return type and purpose without confusing them
- Whether you know
mapwithout a return producesundefinedvalues - Whether you can use
reduceto produce an object, not just a scalar - Whether you know the performance cost of chaining multiple passes and when it matters
- Whether you can distinguish when
forEachis more appropriate thanmap
Follow-Up Questions
- How would you implement
Array.prototype.mapyourself usingreduce? - What is
flatMapand when does it avoid the need for chainingmapfollowed byflat? - If you need to process a very large array (millions of items) with filter and map, what performance concern would you raise about chaining?
- How does React's rendering of list items with
.map()require uniquekeyprops, and what goes wrong without them? - A code review shows
.forEach()being used to build a new array by pushing into an outer variable. What would you suggest instead?
Common Candidate Mistakes
- Forgetting to return a value from a
mapcallback written with curly braces, producing an array ofundefined - Using
mapwhen only side effects are needed (mutation, logging), whenforEachis the semantically correct choice - Not providing an initial value to
reduce, causing it to use the first element as the accumulator and skip it as input - Chaining
filterbeforemapwhenmapfirst would have reduced unnecessary work - Mutating properties of the original array's elements inside a
mapcallback instead of returning a new object
Interview Readiness Checklist
Before you leave this question, make sure you can answer:
- Can you explain what each method returns without looking it up?
- Can you write a
reducethat groups an array of objects by a key into an object of arrays? - Can you explain why forgetting to return inside a
mapcallback produces an array ofundefined? - Can you chain
filter,map, andreducein one expression to solve a multi-step data problem? - Can you explain when to use
forEachinstead ofmapand why the distinction matters?
Summary
map, filter, and reduce are the core higher-order functions for working with arrays without mutation. map transforms every element into a new value and returns an array of the same length. filter selects elements that pass a test and returns a potentially shorter array. reduce folds an entire array into a single output value of any type.
In practice, reduce is the most powerful of the three because it can replicate the behavior of both map and filter. However, for transforming and selecting, map and filter are more readable and should be preferred. reduce shines for aggregation and grouping tasks where the output shape is fundamentally different from the input.
The most common mistakes on these methods are missing return statements in map, using map when forEach is correct, and not providing a reduce initial value. Knowing the grouping pattern for reduce and the performance implications of chaining multiple passes sets a candidate apart from those who only know the basic sum example.
Which one modifies the original array?
None of them. They all return new arrays or values without mutating the original.
Advertisement
Stay Updated
Get the latest frontend challenges, interview questions and tutorials delivered to your inbox.
Advertisement