map, filter, and reduce: How Do They Differ?
Learn how JavaScript map, filter, and reduce differ in output shape, when to use each, and how to chain them correctly.
Expected Interview Answer
map transforms every element into a new array of the same length, filter selects a subset of elements into a new (possibly shorter) array based on a predicate, and reduce folds the whole array down into a single accumulated value of any shape.
All three are non-mutating higher-order array methods that take a callback and iterate once over the source array without changing it. map always returns an array with exactly one output element per input element, so it is the right tool when you need a same-length transformation, like turning objects into ids. filter returns an array containing only the elements for which the predicate callback returns truthy, so the output length is less than or equal to the input length. reduce is the most general: it carries an accumulator through every element and the callback decides how to combine the current accumulator with each item, letting it produce a number, an object, a string, or even another array — which is why map and filter can technically be implemented in terms of reduce, but not the other way around cleanly.
- Declarative, chainable transformations instead of manual for-loops
- map guarantees a same-length, order-preserving output array
- filter cleanly expresses “keep only elements matching a condition”
- reduce generalizes to any accumulation shape, including objects and grouped maps
AI Mentor Explanation
map is like converting every player on the team sheet into their jersey number, one-to-one, so the output list is the same length as the input roster. filter is like walking that same roster and keeping only the players who batted today, dropping the rest, so the output can be shorter. reduce is like walking the whole innings ball by ball and folding every delivery into a single running total score. Each method walks the array once but produces a fundamentally different shaped result.
Step-by-Step Explanation
Step 1
Choose based on output shape
Same-length transform → map; subset → filter; single accumulated value → reduce.
Step 2
map applies the callback per element
Each call returns the new value placed at the same index in the output array.
Step 3
filter applies a boolean predicate
Elements where the predicate returns truthy are kept; others are dropped.
Step 4
reduce threads an accumulator
The callback receives (accumulator, item) and returns the next accumulator; an optional initial value seeds it.
What Interviewer Expects
- Clear statement that map preserves length, filter narrows, reduce collapses
- Awareness that all three are non-mutating and return new values
- Mention that reduce is the most general and can implement map/filter
- A note on always supplying an initial value to reduce to avoid subtle bugs
Common Mistakes
- Using map when the callback has side effects and no return value is needed (should use forEach)
- Forgetting reduce without an initial value uses the first element as the seed, which breaks on empty arrays
- Mutating the array or accumulator inside the callback instead of returning new values
- Chaining map after filter unnecessarily when reduce alone would do both jobs in one pass
Best Answer (HR Friendly)
“map, filter, and reduce all loop over an array without changing the original one. map turns every item into something new and keeps the same number of items. filter keeps only the items that pass a test, so you can end up with fewer. reduce combines everything into one final result, like a total or a summary object.”
Code Example
const orders = [
{ id: 1, total: 42, status: 'paid' },
{ id: 2, total: 15, status: 'pending' },
{ id: 3, total: 90, status: 'paid' },
]
// map: same length, transformed values
const totals = orders.map(order => order.total)
// [42, 15, 90]
// filter: subset matching a predicate
const paidOrders = orders.filter(order => order.status === 'paid')
// [{id:1,...}, {id:3,...}]
// reduce: single accumulated value
const paidRevenue = orders
.filter(order => order.status === 'paid')
.reduce((sum, order) => sum + order.total, 0)
// 132Follow-up Questions
- How would you implement map using reduce?
- What happens if you call reduce on an empty array without an initial value?
- When would forEach be more appropriate than map?
- How do these methods affect readability versus a manual for-loop in a code review?
MCQ Practice
1. Which array method is guaranteed to return an array of the same length as the source?
map produces exactly one output element for every input element, preserving length.
2. What does reduce return if called on an empty array with no initial value?
Reduce with no initial value and an empty array throws because there is nothing to seed the accumulator.
3. Which method is best suited for narrowing an array to elements matching a condition?
filter returns a new array containing only elements for which the predicate returns true.
Flash Cards
map output length? — Always equal to the input array length.
filter output length? — Less than or equal to the input array length, based on a predicate.
reduce output shape? — Any single accumulated value — number, object, string, or array.
Are map/filter/reduce mutating? — No, all three return new values and leave the original array untouched.