I often write for loops with push. Can someone explain which array method fits which job, with examples, and a case where reduce is a bad idea?
DEV3 Developer Forum
When should I use map, filter, reduce, find and flatMap on arrays?
Ask a question
Every post is reviewed first. Usually reviewed within 24 hours.
dev3 ·
0
1 reply
dev3 · Accepted answer
Each method answers a different question.
const users = [
{ id: 1, name: 'Asha', age: 31, tags: ['a', 'b'] },
{ id: 2, name: 'Ben', age: 17, tags: ['b'] },
];
users.map((u) => u.name); // transform each: ['Asha', 'Ben']
users.filter((u) => u.age >= 18); // keep matches: [Asha]
users.find((u) => u.id === 2); // first match or undefined
users.findLast((u) => u.age > 10); // last match (ES2023)
users.some((u) => u.age < 18); // true if any
users.every((u) => u.age > 10); // true if all
users.flatMap((u) => u.tags); // map then flatten one level
users.map((u) => u.age).reduce((a, b) => a + b, 0); // single value: 48
Group by with reduce
const byAge = users.reduce((acc, u) => {
(acc[u.age >= 18 ? 'adult' : 'minor'] ??= []).push(u);
return acc;
}, {});
Newer runtimes also have Object.groupBy(users, fn) and Map.groupBy (check support for your target).
Non-mutating versions (ES2023)
toSorted(), toReversed(), toSpliced(), with(index, value) return copies. sort() and reverse() mutate the original, a classic React state bug.
Sorting
nums.sort((a, b) => a - b); // default sort is lexicographic!
names.sort((a, b) => a.localeCompare(b));
When reduce is a bad idea
Building arrays by spreading the accumulator each step is O(n squared):
// slow for big arrays
arr.reduce((acc, x) => [...acc, x * 2], []);
// better
arr.map((x) => x * 2);
Use reduce for totals and indexes; if the code needs a comment to explain it, use a loop.
Pitfall: map used only for side effects (ignoring the result) should be forEach or for...of.
0