Skip to content

Array methods - map / filter / reduce / find

Map, filter, reduce and find are array methods that are coming from a programming paradigm named functional programming.

To sum it up:

  • Array.prototype.map() takes an array, does something on its elements and returns an array with the transformed elements.
  • Array.prototype.filter() takes an array, decides element by element if it should keep it or not and returns an array with the kept elements only
  • Array.prototype.reduce() takes an array and aggregates the elements into a single value (which is returned)
  • Array.prototype.find() takes an array, and returns the first element that satisfies the provided condition.

I recommend to use them as much as possible in following the principles of functional programming because they are composable, concise and elegant.

With those four methods, you can avoid the use of for and forEach loops in most situations. When you are tempted to do a for loop, try to do it with map, filter, reduce and find composed. You might struggle to do it at first because it requires you to learn a new way of thinking, but once you've got it things get easier.

Sample code

1
2
3
4
5
const numbers = [0, 1, 2, 3, 4, 5, 6];
const doubledNumbers = numbers.map(n => n * 2); // [0, 2, 4, 6, 8, 10, 12]
const evenNumbers = numbers.filter(n => n % 2 === 0); // [0, 2, 4, 6]
const sum = numbers.reduce((prev, next) => prev + next, 0); // 21
const greaterThanFour = numbers.find((n) => n>4); // 5

Compute total grade sum for students with grades 10 or above by composing map, filter and reduce:

const students = [
  { name: "Nick", grade: 10 },
  { name: "John", grade: 15 },
  { name: "Julia", grade: 19 },
  { name: "Nathalie", grade: 9 },
];

const aboveTenSum = students
  .map(student => student.grade) // we map the students array to an array of their grades
  .filter(grade => grade >= 10) // we filter the grades array to keep those 10 or above
  .reduce((prev, next) => prev + next, 0); // we sum all the grades 10 or above one by one

console.log(aboveTenSum) // 44 -- 10 (Nick) + 15 (John) + 19 (Julia), Nathalie below 10 is ignored

Explanation

Let's consider the following array of numbers for our examples:

const numbers = [0, 1, 2, 3, 4, 5, 6];

Array.prototype.map()

1
2
3
4
const doubledNumbers = numbers.map(function(n) {
  return n * 2;
});
console.log(doubledNumbers); // [0, 2, 4, 6, 8, 10, 12]

What's happening here? We are using .map on the numbers array, the map is iterating on each element of the array and passes it to our function. The goal of the function is to produce and return a new value from the one passed so that map can replace it.

Let's extract this function to make it more clear, just for this once:

1
2
3
const doubleN = function(n) { return n * 2; };
const doubledNumbers = numbers.map(doubleN);
console.log(doubledNumbers); // [0, 2, 4, 6, 8, 10, 12]

Note : You will frequently encounter this method used in combination with arrow functions

const doubledNumbers = numbers.map(n => n * 2);
console.log(doubledNumbers); // [0, 2, 4, 6, 8, 10, 12]

numbers.map(doubleN) produces [doubleN(0), doubleN(1), doubleN(2), doubleN(3), doubleN(4), doubleN(5), doubleN(6)] which is equal to [0, 2, 4, 6, 8, 10, 12].

Note: If you do not need to return a new array and just want to do a loop that has side effects, you might just want to use a for / forEach loop instead of a map.

Array.prototype.filter()

1
2
3
4
const evenNumbers = numbers.filter(function(n) {
  return n % 2 === 0; // true if "n" is par, false if "n" isn't
});
console.log(evenNumbers); // [0, 2, 4, 6]

Note : You will frequently encounter this method used in combination with arrow functions

const evenNumbers = numbers.filter(n => n % 2 === 0);
console.log(evenNumbers); // [0, 2, 4, 6]

We are using .filter on the numbers array, filter is iterating on each element of the array and passes it to our function. The goal of the function is to return a boolean that will determine whether the current value will be kept or not. Filter then returns the array with only the kept values.

Array.prototype.reduce()

The reduce method goal is to reduce all elements of the array it iterates on into a single value. How it aggregates those elements is up to you.

1
2
3
4
5
6
7
8
const sum = numbers.reduce(
  function(acc, n) {
    return acc + n;
  },
  0 // accumulator variable value at first iteration step
);

console.log(sum) // 21

Note : You will frequently encounter this method used in combination with arrow functions

const sum = numbers.reduce((acc, n) => acc + n, 0);
console.log(sum) // 21

Just like for .map and .filter methods, .reduce is applied on an array and takes a function as the first parameter.

This time though, there are changes:

  • .reduce takes two parameters

The first parameter is a function that will be called at each iteration step.

The second parameter is the value of the accumulator variable (acc here) at the first iteration step (read next point to understand).

  • Function parameters

The function you pass as the first parameter of .reduce takes two parameters. The first one (acc here) is the accumulator variable, whereas the second parameter (n) is the current element.

The accumulator variable is equal to the return value of your function at the previous iteration step. At the first step of the iteration, acc is equal to the value you passed as .reduce second parameter.

At first iteration step

acc = 0 because we passed in 0 as the second parameter for reduce

n = 0 first element of the number array

Function returns acc + n --> 0 + 0 --> 0

At second iteration step

acc = 0 because it's the value the function returned at the previous iteration step

n = 1 second element of the number array

Function returns acc + n --> 0 + 1 --> 1

At third iteration step

acc = 1 because it's the value the function returned at the previous iteration step

n = 2 third element of the number array

Function returns acc + n --> 1 + 2 --> 3

At fourth iteration step

acc = 3 because it's the value the function returned at the previous iteration step

n = 3 fourth element of the number array

Function returns acc + n --> 3 + 3 --> 6

[...] At last iteration step

acc = 15 because it's the value the function returned at the previous iteration step

n = 6 last element of the number array

Function returns acc + n --> 15 + 6 --> 21

As it is the last iteration step, .reduce returns 21.

Array.prototype.find()

1
2
3
4
const greaterThanZero = numbers.find(function(n) {
  return n > 0; // return number just greater than 0 is present
});
console.log(greaterThanZero); // 1

Note : You will frequently encounter this method used in combination with arrow functions

We are using .find on the numbers array, .find is iterating on each element of the array and passes it to our function, until the condition is met. The goal of the function is to return the element that satisfies the current testing function. The .find method executes the callback function once for each index of the array until the callback returns a truthy value.

Note : It immediately returns the value of that element (that satisfies the condition) if found. Otherwise, returns undefined.

External Resource