map, filter, reduce & Anti-patterns
map naye array banata hai, filter chhanta lagata hai, aur reduce ek value mein sab squeeze kar deta hai.
map(callback) creates a NEW array by applying a callback to every element. The callback receives (element, index, array).
filter(callback) creates a NEW array with only elements where the callback returns truthy.
Both skip holes (callback not called for empty slots). Both do NOT mutate the original array.
const users = [
{ name: "Sai", active: true },
{ name: "Ali", active: false },
{ name: "Ravi", active: true }
];
// map — transform data
const names = users.map(user => user.name);
console.log(names); // ["Sai", "Ali", "Ravi"]
// filter — select data
const activeUsers = users.filter(user => user.active);
console.log(activeUsers);
// Chaining map and filter
const activeNames = users
.filter(user => user.active)
.map(user => user.name.toUpperCase());
console.log(activeNames); // ["SAI", "RAVI"]
// ANTI-PATTERN: map for side effects
// const bad = users.map(user => { fetch("/log", user); return user; }); // BAD!
// GOOD: forEach for side effects
// users.forEach(user => fetch("/log", user));
reduce(callback, initialValue) accumulates array elements into a single value. The callback receives (accumulator, currentValue, index, array).
Without initialValue: Uses first element as initial, starts from index 1. Empty array without initialValue throws TypeError!
The accumulator can be anything: number, string, array, or object.
const nums = [1, 2, 3, 4, 5];
// Sum
const sum = nums.reduce((acc, cur) => acc + cur, 0);
console.log(sum); // 15
// Find Max
const max = nums.reduce((a, b) => (a > b ? a : b), -Infinity);
// Grouping objects by property
const items = [
{ type: "food", name: "Biryani" },
{ type: "drink", name: "Chai" },
{ type: "food", name: "Haleem" }
];
const grouped = items.reduce((acc, item) => {
if (!acc[item.type]) acc[item.type] = [];
acc[item.type].push(item.name);
return acc;
}, {});
console.log(grouped);
// { food: ["Biryani", "Haleem"], drink: ["Chai"] }
TypeError: Reduce of empty array with no initial value. Provide 0 for sums, [] for arrays, {} for objects.find(callback): Returns FIRST element that matches. Stops iterating after finding. Returns undefined if not found.
findIndex(callback): Same as find, but returns index (-1 if not found).
some(callback): Returns true if ANY element passes. Short-circuits on first true.
every(callback): Returns true if ALL elements pass. Short-circuits on first false.
filter always scans the entire array; find stops at the first match.const users = [
{ id: 1, name: "Sai", age: 25 },
{ id: 2, name: "Ali", age: 17 },
{ id: 3, name: "Ravi", age: 30 }
];
// find — get the first match
const adult = users.find(u => u.age >= 18);
console.log(adult); // { id: 1, name: "Sai"... }
// findIndex — get the index
const minorIdx = users.findIndex(u => u.age < 18);
console.log(minorIdx); // 1
// some — is there at least one?
const hasMinor = users.some(u => u.age < 18);
console.log(hasMinor); // true
// every — are they all adults?
const allAdults = users.every(u => u.age >= 18);
console.log(allAdults); // falseflat(depth): Flattens nested arrays up to specified depth. Default depth is 1.
flatMap(callback): Maps then flattens 1 level. More efficient than map().flat().
flat(Infinity) fully flattens any depth. Holes are removed during flattening.
// flat — default depth 1
const nested = [1, [2, 3], [4, [5, 6]]];
console.log(nested.flat()); // [1, 2, 3, 4, [5, 6]]
console.log(nested.flat(2)); // [1, 2, 3, 4, 5, 6]
console.log(nested.flat(Infinity)); // [1, 2, 3, 4, 5, 6]
// flatMap — map + flat(1) in one step
const sentences = ["Hello World", "Good Morning"];
const words = sentences.flatMap(s => s.split(" "));
console.log(words); // ["Hello", "World", "Good", "Morning"]
// Filtering and mapping simultaneously with flatMap
const result = [1, -2, 3, -4].flatMap(n => n > 0 ? [n * 2] : []);
console.log(result); // [2, 6]
ANTI-PATTERN 1: Using [...acc, item] inside reduce. This creates a new array every iteration, making it O(n²). Use push or filter instead.
ANTI-PATTERN 2: Chaining 10+ methods. Each step creates a new intermediate array. Use a single for-loop for performance-critical code.
ANTI-PATTERN 3: Using map for side effects. map returns an array; if you ignore the return value, use forEach instead.
// ANTI-PATTERN O(n^2): Spread in reduce
const evensBad = nums.reduce((acc, n) => {
if (n % 2 === 0) return [...acc, n]; // Copies ENTIRE acc every loop!
return acc;
}, []);
// GOOD O(n): Mutate the accumulator (it is our local array)
const evensGood = nums.reduce((acc, n) => {
if (n % 2 === 0) acc.push(n);
return acc;
}, []);
// BEST: Just use filter!
const evensBest = nums.filter(n => n % 2 === 0);
// ANTI-PATTERN: Excessive chaining (5 intermediate arrays!)
const result = data
.map(transform1)
.filter(predicate1)
.map(transform2)
.filter(predicate2)
.sort(compare);
// GOOD for perf: Single pass (0 intermediate arrays)
const result = [];
for (const item of data) {
const t1 = transform1(item);
if (!predicate1(t1)) continue;
const t2 = transform2(t1);
if (!predicate2(t2)) continue;
result.push(t2);
}
result.sort(compare);
Lo kar liya — Key Points:
- ✅ map transforms every element; filter selects elements; both return new arrays and skip holes
- ✅ reduce accumulates array elements into a single value; always provide an initialValue to avoid bugs
- ✅ find, some, and every short-circuit — they stop iterating as soon as the result is known
- ✅ flat flattens nested arrays; flatMap maps and then flattens one level (more efficient than map().flat())
- ✅ Using
[...acc, item]inside reduce is O(n²) — useacc.push()or just use filter() - ✅ Use map for transformations, forEach for side effects; never use map if you ignore its return value
Want to track your progress?
Log in to save your place and pick up where you left off.
Progress track karna chahte ho?
Login karo apni progress save karne ke liye aur jahan chhoda tha wahan se shuru karo.
Login