MarzleyTech Learn

Home / Learn / JavaScript / Array methods: map, filter, reduce, find and sort

Array methods: map, filter, reduce, find and sort

Loops work, but modern JavaScript uses array methods that say what you want instead of how to loop. They make code shorter and easier to read. Each takes a small function (often an arrow function) that runs for every item.

Arrow functions in one minute

JavaScript
function double(n) { return n * 2; }   // normal function
const double2 = (n) => n * 2;           // arrow function, same thing
const add = (a, b) => a + b;

Our sample data

JavaScript · runs live in the interactive lesson
const products = [
  { name: "Unga 2kg", price: 180, category: "food", stock: 12 },
  { name: "Sugar 1kg", price: 160, category: "food", stock: 0 },
  { name: "Soap bar", price: 60, category: "home", stock: 30 },
  { name: "Cooking oil 1L", price: 350, category: "food", stock: 7 },
  { name: "Matchbox", price: 10, category: "home", stock: 100 },
];

// forEach: do something with each item (returns nothing)
products.forEach((p) => console.log(p.name, "- KSh", p.price));

map: transform every item into a new array

JavaScript · runs live in the interactive lesson
const prices = [180, 160, 60, 350];
const withVat = prices.map((p) => Math.round(p * 1.16));
console.log(withVat); // [209, 186, 70, 406]

const names = ["amina", "otieno", "kiprop"];
console.log(names.map((n) => n[0].toUpperCase() + n.slice(1)));

map always returns an array of the same length.

filter: keep only matching items

JavaScript · runs live in the interactive lesson
const products = [
  { name: "Unga 2kg", price: 180, stock: 12 },
  { name: "Sugar 1kg", price: 160, stock: 0 },
  { name: "Cooking oil 1L", price: 350, stock: 7 },
];
const inStock = products.filter((p) => p.stock > 0);
console.log(inStock.map((p) => p.name));        // ["Unga 2kg", "Cooking oil 1L"]
const cheap = products.filter((p) => p.price < 200);
console.log(cheap.length);                       // 2

reduce: boil an array down to one value

JavaScript · runs live in the interactive lesson
const cart = [
  { item: "Unga", price: 180, qty: 2 },
  { item: "Oil", price: 350, qty: 1 },
  { item: "Soap", price: 60, qty: 3 },
];
const total = cart.reduce((sum, line) => sum + line.price * line.qty, 0);
console.log("Total: KSh", total);  // 890

reduce((accumulator, item) => ..., startValue): the accumulator carries the running result. Always give a start value (here 0).

find, findIndex, some, every, includes

JavaScript · runs live in the interactive lesson
const users = [
  { id: 1, name: "Wanjiku", paid: true },
  { id: 2, name: "Omondi", paid: false },
  { id: 3, name: "Chebet", paid: true },
];
console.log(users.find((u) => u.id === 2));          // the Omondi object
console.log(users.findIndex((u) => u.name === "Chebet")); // 2
console.log(users.some((u) => !u.paid));             // true: someone hasn't paid
console.log(users.every((u) => u.paid));             // false
console.log(["M-Pesa", "Card"].includes("Card"));    // true

sort (careful!)

JavaScript · runs live in the interactive lesson
const nums = [100, 25, 3, 1000];
console.log([...nums].sort());               // [100, 1000, 25, 3]  sorted as TEXT!
console.log([...nums].sort((a, b) => a - b)); // [3, 25, 100, 1000]  lowest first
console.log([...nums].sort((a, b) => b - a)); // highest first

const people = [{ n: "Zawadi", age: 31 }, { n: "Baraka", age: 22 }];
people.sort((a, b) => a.n.localeCompare(b.n));  // alphabetical
console.log(people.map((p) => p.n));

sort changes the original array. Copy it first with [...array] if you need to keep the original order.

Chaining: combine methods

JavaScript · runs live in the interactive lesson
const sales = [
  { agent: "Achieng", amount: 1200, month: "Jan" },
  { agent: "Kamau", amount: 800, month: "Jan" },
  { agent: "Achieng", amount: 2300, month: "Feb" },
  { agent: "Kamau", amount: 400, month: "Feb" },
];
const achiengTotal = sales
  .filter((s) => s.agent === "Achieng")
  .map((s) => s.amount)
  .reduce((a, b) => a + b, 0);
console.log("Achieng sold KSh", achiengTotal); // 3500

Cheat sheet

MethodReturnsUse it to
mapNew array, same lengthTransform each item
filterNew array, maybe shorterKeep matching items
reduceOne valueTotals, counts, grouping
findFirst match or undefinedLook up one item
some / everytrue / falseCheck a condition
sortThe same array, sortedOrder items
sliceA copy of partPagination, top 3
includestrue / falseIs a value in the list?

Why array methods matter

Lists are the most common data in apps: products, orders, students, transactions, search results, chat messages. Array methods let you transform, filter and summarise lists in clear, short code instead of long for loops with counters. They are used everywhere in modern JavaScript, and React displays lists almost entirely with map. Interviewers often ask candidates to solve small problems with map, filter and reduce.

Choosing the right method

You want to...UseReturns
Change every itemmapNew array, same length
Keep some itemsfilterNew array, same or shorter
Get one value (total, max, object)reduceAnything
Get the first matchfind / findIndexItem or undefined / index or -1
Get the last matchfindLast / findLastIndexItem / index
Ask "any?" / "all?"some / everytrue/false
Just do something with eachforEachundefined
Flatten nested listsflat / flatMapNew array

reduce in depth

reduce can build any result, not just numbers:

JavaScript · runs live in the interactive lesson
const sales = [
  { town: "Nakuru", product: "Unga", amount: 1800 },
  { town: "Thika", product: "Sugar", amount: 840 },
  { town: "Nakuru", product: "Oil", amount: 1400 },
  { town: "Eldoret", product: "Unga", amount: 900 },
];

const totalsByTown = sales.reduce((acc, s) => {
  acc[s.town] = (acc[s.town] ?? 0) + s.amount;
  return acc;
}, {});
console.log(totalsByTown);

const biggest = sales.reduce((best, s) => (s.amount > best.amount ? s : best));
console.log("Biggest sale:", biggest);

const stats = sales.reduce(
  (acc, s) => ({ count: acc.count + 1, sum: acc.sum + s.amount }),
  { count: 0, sum: 0 }
);
console.log(`Average sale: KSh ${(stats.sum / stats.count).toFixed(0)}`);

Always give reduce a starting value (the second argument). Without it, an empty array throws an error, and the first item is used as the accumulator, which causes bugs when items are objects.

Copying vs changing the original

Some methods change (mutate) the original array; others return a new one:

Changes the originalReturns a new array
push, pop, shift, unshift, splice, sort, reverse, fillmap, filter, slice, concat, toSorted, toReversed, toSpliced, with
JavaScript · runs live in the interactive lesson
const marks = [67, 82, 45, 90];
const sorted = marks.toSorted((a, b) => b - a);   // new array, original untouched
console.log(marks, sorted);
const copy = [...marks].sort((a, b) => a - b);    // older way: copy first, then sort
console.log(copy);
const updated = marks.with(2, 50);                // replace index 2 in a copy
console.log(updated, marks);

In frameworks like React, prefer the non-mutating versions so changes are detected.

Sorting objects by several fields

JavaScript · runs live in the interactive lesson
const students = [
  { name: "Wanjiru", form: 2, mean: 71.5 },
  { name: "Otieno", form: 1, mean: 80.2 },
  { name: "Akinyi", form: 2, mean: 84.0 },
  { name: "Baraka", form: 1, mean: 80.2 },
];
const ordered = students.toSorted(
  (a, b) => a.form - b.form || b.mean - a.mean || a.name.localeCompare(b.name)
);
ordered.forEach(s => console.log(`Form ${s.form}  ${s.name.padEnd(8)} ${s.mean}`));

The || chain means: sort by form; if equal, by mean (highest first); if still equal, by name.

flat, flatMap and Array.from

JavaScript · runs live in the interactive lesson
const orders = [
  { id: 1, items: ["Unga", "Oil"] },
  { id: 2, items: ["Sugar"] },
  { id: 3, items: ["Unga", "Salt", "Tea"] },
];
const allItems = orders.flatMap(o => o.items);
console.log(allItems);
console.log([...new Set(allItems)]);                     // unique items

console.log([[1, 2], [3, [4, 5]]].flat(2));              // [1, 2, 3, 4, 5]
console.log(Array.from({ length: 5 }, (_, i) => (i + 1) * 100));  // [100, 200, 300, 400, 500]
console.log(Array.from("KENYA"));

Pagination and top-N

JavaScript · runs live in the interactive lesson
const items = Array.from({ length: 23 }, (_, i) => `Product ${i + 1}`);
const perPage = 10;
const pages = Math.ceil(items.length / perPage);
for (let page = 1; page <= pages; page++) {
  const slice = items.slice((page - 1) * perPage, page * perPage);
  console.log(`Page ${page}/${pages}:`, slice[0], "...", slice.at(-1));
}

at(-1) gets the last item, which is neater than arr[arr.length - 1].

A complete data task: a sales report

JavaScript · runs live in the interactive lesson
const transactions = [
  { date: "2026-09-01", type: "sale", amount: 2500, method: "mpesa" },
  { date: "2026-09-01", type: "refund", amount: 300, method: "mpesa" },
  { date: "2026-09-02", type: "sale", amount: 1200, method: "cash" },
  { date: "2026-09-02", type: "sale", amount: 4100, method: "mpesa" },
  { date: "2026-09-03", type: "sale", amount: 650, method: "card" },
];
const sales = transactions.filter(t => t.type === "sale");
const refunds = transactions.filter(t => t.type === "refund");
const sum = list => list.reduce((s, t) => s + t.amount, 0);
const byMethod = Object.groupBy
  ? Object.groupBy(sales, t => t.method)
  : sales.reduce((acc, t) => ((acc[t.method] ??= []).push(t), acc), {});

console.log("Gross sales:", sum(sales));
console.log("Refunds:", sum(refunds));
console.log("Net:", sum(sales) - sum(refunds));
for (const [method, list] of Object.entries(byMethod)) {
  console.log(`  ${method.padEnd(6)} ${String(list.length).padStart(2)} sales  KSh ${sum(list)}`);
}
console.log("Any sale above 4,000?", sales.some(t => t.amount > 4000));
console.log("All amounts positive?", transactions.every(t => t.amount > 0));

Performance notes

  • Chaining filter().map() loops twice; that's fine for hundreds or thousands of items. For huge arrays in hot code, a single reduce or for loop can be faster.
  • includes and find scan the whole array. For repeated lookups by id, build a Map once: new Map(products.map(p => [p.id, p])).
  • Avoid forEach with async callbacks: it doesn't wait. Use for...of with await, or Promise.all(items.map(async ...)).

Common mistakes

MistakeResultFix
Forgetting return in a {} arrowmap gives [undefined, ...]x => x * 2 or x => { return x * 2; }
Returning an object from an arrow without bracketsx => { name: x } returns undefinedx => ({ name: x })
sort() on numbers without a compare functionSorted as textsort((a, b) => a - b)
reduce without a starting valueErrors on empty arraysAlways pass one
Using map just to loopWasted new arrayforEach or for...of

Practice

  1. From the products list, get the names of in-stock food items sorted by price.
  2. Calculate the total stock value (price * stock) with reduce.
  3. Find the most expensive product in each category.
  4. Turn ["Nairobi", "Mombasa", "Kisumu"] into [{ id: 1, town: "Nairobi" }, ...].
  5. Given an array of words, count how many times each appears.
Think about it: Why does [1, 2, 3].map(n => { n * 2 }) give [undefined, undefined, undefined]?Show answer

Curly braces after => start a function body, and a body needs an explicit return. Without it the function returns undefined. Use the short form n => n * 2 or write { return n * 2; }.

Check yourself

  1. Which method creates a new array by transforming every item?

    Show answer

    map

  2. Which method keeps only the items that pass a test?

    Show answer

    filter

  3. Which method turns an array into a single value like a total?

    Show answer

    reduce

  4. What does [10, 9, 100].sort() give first: 10 or 9 or 100?

    Show answer

    10 · Without a compare function, sort compares as text.

  5. Which method returns the first item that matches?

    Show answer

    find

  6. Which method returns a sorted copy without changing the original array?

    Show answer

    toSorted

  7. Which method maps each item to an array and flattens the result one level?

    Show answer

    flatMap

  8. Which method gets the last item using a negative index?

    Show answer

    at

Exercise

Use reduce to add up the array [180, 350, 60] and log the total. The output should be 590.

Do this exercise in the live editor

Lesson 7 of 21 in JavaScript · Printable course notes