Academic Block

Array Methods: map, filter, and reduce Get Certified

Three of the most useful array methods in modern JavaScript are map(), filter(), and reduce(). They let you transform, select, and combine the values in an array without writing long loops by hand.

In this lesson you will learn what each method does, how they differ, and how to chain them together for clear, readable data processing.

map(): Transforming Every Element

map() creates a new array by calling a function on every element of the original array. The original array is never modified.

What this code does: map multiplies every price by 1.1 and returns a new array. The original prices array stays unchanged.

const prices = [10, 25, 40];
const inflated = prices.map(function (price) {
    return price * 1.1;
});
console.log(inflated);
console.log(prices); // original unchanged

What this code does: Arrow-function form of map. Each product name is converted to uppercase.

const products = ["laptop", "phone", "tablet"];
const uppercased = products.map(name => name.toUpperCase());
console.log(uppercased);

filter(): Keeping Only What Matches

filter() builds a new array that contains only the elements for which the callback returns a truthy value.

What this code does: filter keeps only the scores that are 50 or higher.

const scores = [42, 88, 55, 91, 33];
const passing = scores.filter(function (score) {
    return score >= 50;
});
console.log(passing);

What this code does: Filter an array of objects, keeping only the items that are in stock.

const inventory = [
    { name: "Keyboard", inStock: true },
    { name: "Mouse", inStock: false },
    { name: "Monitor", inStock: true }
];
const available = inventory.filter(item => item.inStock);
console.log(available);

Combining map() and filter()

You can chain filter() and map() to first select the elements you care about and then transform them.

What this code does: First keep only items priced above 10, then extract just their names.

const items = [
    { name: "Pen", price: 2 },
    { name: "Notebook", price: 12 },
    { name: "Backpack", price: 45 },
    { name: "Eraser", price: 1 }
];
const expensiveNames = items
    .filter(item => item.price > 10)
    .map(item => item.name);
console.log(expensiveNames);

reduce(): Combining Everything Into One Value

reduce() walks through an array and builds a single result (a number, an object, another array, etc.) by repeatedly applying a callback that receives an accumulator and the current element.

What this code does: reduce adds every expense together, starting from an initial value of 0.

const expenses = [45.5, 12.99, 89.0, 6.25];
const totalSpent = expenses.reduce(function (accumulator, amount) {
    return accumulator + amount;
}, 0);
console.log(totalSpent);

Using reduce() to Find a Maximum

Because the accumulator can hold any value, reduce() can also be used to find the highest-rated item, the longest string, and so on.

What this code does: Walk through the books and keep the one with the highest rating.

const books = [
    { title: "Dune", rating: 4.8 },
    { title: "Circe", rating: 4.6 },
    { title: "Educated", rating: 4.7 }
];
const topRatedBook = books.reduce(function (best, current) {
    return current.rating > best.rating ? current : best;
});
console.log(topRatedBook);

Using reduce() to Build an Object

A common pattern is to start with an empty object and use reduce() to count how many times each value appears.

What this code does: Count how many times each order item appears, building a frequency object.

const orders = ["pizza", "salad", "pizza", "soup", "pizza", "salad"];
const orderCounts = orders.reduce(function (counts, item) {
    counts[item] = (counts[item] || 0) + 1;
    return counts;
}, {});
console.log(orderCounts);

Chaining map(), filter(), and reduce()

The three methods can be chained so that each step does one clear job: select, transform, then combine.

What this code does: Keep only affordable items, compute each line-item total, then sum those totals.

const cartItems = [
    { name: "Notebook", price: 4.5, quantity: 3 },
    { name: "Desk Lamp", price: 22.0, quantity: 1 },
    { name: "Pen Set", price: 8.0, quantity: 2 },
    { name: "Monitor Stand", price: 35.0, quantity: 1 }
];
const totalForAffordableItems = cartItems
    .filter(item => item.price < 25)
    .map(item => item.price * item.quantity)
    .reduce((sum, subtotal) => sum + subtotal, 0);
console.log(totalForAffordableItems);

When a Regular Loop Might Be Better

Sometimes a plain for loop is clearer, especially when you need to stop as soon as a match is found.

What this code does: A regular loop finds the first item priced above 20 and then stops. This is more efficient than filtering the whole array when only the first match is needed.

const cartItems = [
    { name: "Notebook", price: 4.5 },
    { name: "Desk Lamp", price: 22.0 },
    { name: "Monitor Stand", price: 35.0 }
];
// A regular loop makes sense here since we want to stop early.
let firstExpensiveItem = null;
for (let i = 0; i < cartItems.length; i++) {
    if (cartItems[i].price > 20) {
        firstExpensiveItem = cartItems[i];
        break;
    }
}
console.log(firstExpensiveItem);

map() vs. filter() vs. reduce()

Method Returns Typical Use
map() A new array, same length Transform each element
filter() A new array, same length or shorter Keep only elements that match a condition
reduce() A single value (any type) Combine all elements into one result

Practical Example

Let's calculate an average product rating using filter(), map(), and reduce() together.

What this code does: Filter verified reviews, map to their star ratings, then reduce to a total. Chaining keeps each step focused and readable.

const reviews = [
    { product: "Headphones", stars: 5, verified: true },
    { product: "Headphones", stars: 2, verified: false },
    { product: "Headphones", stars: 4, verified: true },
    { product: "Headphones", stars: 5, verified: true }
];
const verifiedStars = reviews
    .filter(review => review.verified)
    .map(review => review.stars);
const averageRating = verifiedStars.reduce((sum, stars) => sum + stars, 0) / verifiedStars.length;
console.log("Average rating from verified reviews:", averageRating.toFixed(1));

Common Mistakes With map, filter, and reduce

  • Forgetting to return a value from the callback passed to map(), resulting in an array full of undefined.
  • Using map() when forEach() would be more appropriate, because the new array it returns is never used.
  • Forgetting the initial value in reduce(), causing unexpected behavior on an empty array.
  • Using filter() just to find one matching element, when find() would stop searching immediately after a match instead of checking every element.
  • Chaining so many methods together that the resulting one-liner becomes harder to read than a few clearly named steps.

Best Practices for map, filter, and reduce

  • Use map() only when you need the transformed array itself — use forEach() for side effects like logging.
  • Always provide an initial value to reduce() when working with sums, counts, or objects.
  • Break especially long chains into intermediate variables with descriptive names, to keep the logic easy to follow.
  • Reach for more specific methods like find() or some() when they match your intent more precisely than filter().
  • Keep callback functions small and focused on a single transformation or condition.

Quick Summary

  • map() transforms every element into a new array of the same length.
  • filter() keeps only the elements that pass a given test.
  • reduce() combines all elements into a single result, using an accumulator.
  • These methods can be chained together to express multi-step data processing clearly.
  • None of the three modify the original array — they all return new values.
  • A regular loop (or a more specific method like find()) is sometimes a better fit than forcing everything into these three methods.

Try It Yourself

Modify the code below. Try changing the filter condition, or adding another step to the chain.

What this code does: Practice example: filter passing students, extract grades, then average them. Try changing the cutoff or adding another step, then click Test My Code.

const students = [
    { name: "Noah", grade: 78 },
    { name: "Aisha", grade: 92 },
    { name: "Liam", grade: 65 },
    { name: "Zara", grade: 88 }
];
const passingAverage = students
    .filter(student => student.grade >= 70)
    .map(student => student.grade)
    .reduce((sum, grade, index, array) => {
        sum += grade;
        if (index === array.length - 1) {
            return sum / array.length;
        }
        return sum;
    }, 0);
console.log("Average passing grade:", passingAverage);
Tip: A useful way to decide between these methods: ask "do I want the same number of items back, transformed?" (map), "do I want fewer items back?" (filter), or "do I want just one final answer?" (reduce).

Understanding map(), filter(), and reduce() is essential before moving on to other array methods like find(), some(), and every(), and more advanced JavaScript concepts.

🧪 Test Your JavaScript Code

Edit the code on the left and click "Run Code" to see the console output on the right.

📝 JavaScript Code
👁 Console Output

Click "Run Code" to see the output here.

Ctrl + Enter to run code Esc to close