Skip to content
Plurafy

Array Methods and Functional Programming

Mastering array manipulation with map, filter, reduce and other methods

Convert an array of user objects into a single object mapping user IDs to user names, filtering only active users. How can you do this with a single array operation?

Array methods like map, filter, and reduce are foundational to functional programming in JavaScript. They allow you to transform data in declarative, composable ways.

const users = [
{ id: 1, name: 'Alice', active: true },
{ id: 2, name: 'Bob', active: false },
{ id: 3, name: 'Charlie', active: true },
{ id: 4, name: 'David', active: false }
];
// ❌ Imperative approach
const result1 = {};
for (const user of users) {
if (user.active) {
result1[user.id] = user.name;
}
}
// ✅ Functional approach
const result2 = users
.filter(user => user.active)
.reduce((acc, user) => ({
...acc,
[user.id]: user.name
}), {});
// ✅ One-pass reduce
const result3 = users.reduce((acc, user) => {
if (user.active) {
acc[user.id] = user.name;
}
return acc;
}, {});
console.log(result3); // { 1: 'Alice', 3: 'Charlie' }
// map: Transform each element
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(n => n * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
// filter: Keep elements matching condition
const evens = numbers.filter(n => n % 2 === 0);
console.log(evens); // [2, 4]
// reduce: Accumulate into single value
const sum = numbers.reduce((acc, n) => acc + n, 0);
console.log(sum); // 15
// find: Get first matching element
const firstEven = numbers.find(n => n % 2 === 0);
console.log(firstEven); // 2
// findIndex: Get index of first match
const index = numbers.findIndex(n => n % 2 === 0);
console.log(index); // 1
// some: Check if any element matches
const hasEven = numbers.some(n => n % 2 === 0);
console.log(hasEven); // true
// every: Check if all elements match
const allPositive = numbers.every(n => n > 0);
console.log(allPositive); // true
// includes: Check if contains value
console.log([1, 2, 3].includes(2)); // true
// Grouping by property
const items = [
{ category: 'fruit', name: 'apple' },
{ category: 'fruit', name: 'banana' },
{ category: 'vegetable', name: 'carrot' }
];
const grouped = items.reduce((acc, item) => {
const key = item.category;
acc[key] = acc[key] || [];
acc[key].push(item.name);
return acc;
}, {});
console.log(grouped);
// { fruit: ['apple', 'banana'], vegetable: ['carrot'] }
// Counting occurrences
const words = ['apple', 'banana', 'apple', 'carrot', 'banana', 'apple'];
const counts = words.reduce((acc, word) => {
acc[word] = (acc[word] || 0) + 1;
return acc;
}, {});
console.log(counts);
// { apple: 3, banana: 2, carrot: 1 }
// Flattening arrays
const nested = [[1, 2], [3, 4], [5, 6]];
const flat = nested.reduce((acc, arr) => acc.concat(arr), []);
console.log(flat); // [1, 2, 3, 4, 5, 6]
// Or use flat()
console.log(nested.flat()); // [1, 2, 3, 4, 5, 6]
// Efficient data transformation pipeline
const data = [
{ id: 1, score: 45, subject: 'math' },
{ id: 2, score: 85, subject: 'math' },
{ id: 3, score: 92, subject: 'english' },
{ id: 4, score: 78, subject: 'math' },
{ id: 5, score: 65, subject: 'english' }
];
const result = data
.filter(item => item.score >= 70) // Pass/fail threshold
.filter(item => item.subject === 'math') // Math only
.map(item => ({ name: `Student ${item.id}`, score: item.score }))
.sort((a, b) => b.score - a.score) // Highest first
.slice(0, 2); // Top 2
console.log(result);
// [
// { name: 'Student 2', score: 85 },
// { name: 'Student 4', score: 78 }
// ]
// Create once, reuse
const numbers = Array.from({ length: 1000000 }, (_, i) => i);
// ❌ Chain creates intermediate arrays
const result1 = numbers
.filter(n => n % 2 === 0) // Creates new array
.map(n => n * 2) // Creates another array
.slice(0, 10); // Filters to 10
// ✅ Reduce in one pass (more efficient)
const result2 = numbers.reduce((acc, n) => {
if (acc.length >= 10) return acc;
if (n % 2 === 0) acc.push(n * 2);
return acc;
}, []);
// ✅ Use for loop for max performance if needed
const result3 = [];
for (let i = 0; i < numbers.length && result3.length < 10; i++) {
if (numbers[i] % 2 === 0) {
result3.push(numbers[i] * 2);
}
}
// flatMap: map then flatten
const sentences = ['hello world', 'how are you'];
const words = sentences.flatMap(s => s.split(' '));
console.log(words); // ['hello', 'world', 'how', 'are', 'you']
// toReversed (ES2023): Create reversed copy
const arr = [1, 2, 3];
const reversed = arr.toReversed();
console.log(arr); // [1, 2, 3] - original unchanged
console.log(reversed); // [3, 2, 1]
// toSorted (ES2023): Create sorted copy
const unsorted = [3, 1, 2];
const sorted = unsorted.toSorted();
console.log(unsorted); // [3, 1, 2] - original unchanged
console.log(sorted); // [1, 2, 3]
// with (ES2023): Create modified copy
const original = ['a', 'b', 'c'];
const modified = original.with(1, 'B');
console.log(original); // ['a', 'b', 'c'] - unchanged
console.log(modified); // ['a', 'B', 'c']

Practical Example: Data Processing Pipeline

Section titled “Practical Example: Data Processing Pipeline”
// Process sales data
const sales = [
{ product: 'A', region: 'North', amount: 100, date: '2024-01-15' },
{ product: 'B', region: 'South', amount: 150, date: '2024-01-20' },
{ product: 'A', region: 'North', amount: 200, date: '2024-02-10' },
{ product: 'C', region: 'East', amount: 75, date: '2024-02-15' },
{ product: 'B', region: 'West', amount: 125, date: '2024-03-05' }
];
// Analyze sales by product
const analysis = sales
.reduce((acc, sale) => {
if (!acc[sale.product]) {
acc[sale.product] = {
product: sale.product,
total: 0,
count: 0,
regions: new Set()
};
}
acc[sale.product].total += sale.amount;
acc[sale.product].count += 1;
acc[sale.product].regions.add(sale.region);
return acc;
}, {});
// Transform to array and calculate average
const summary = Object.values(analysis)
.map(item => ({
...item,
average: item.total / item.count,
regions: Array.from(item.regions)
}))
.sort((a, b) => b.total - a.total);
console.log(summary);