Understanding map(), filter() and reduce() in JavaScript
Tags: javascript, webdev, beginners
Published: 2021-06-14 11:21:03

## Table of Contents
1. [Introduction](#introduction)
2. [map()](#what-is-map)
3. [filter()](#what-is-filter)
4. [reduce()](#what-is-reduce)
5. [Resources](#resources)



## Introduction

In the previous post we talked about [First Class Functions ](https://dev.to/zagaris/understanding-first-class-functions-in-javascript-866) and how JavaScript treat functions as a first-class-citizens. 

`Higher Orders Functions` are functions that either take one or more functions as its arguments and/or return a function. This is a concept that was born out of functional programming. JavaScript, is a language that uses a lot of the functional programming concepts and `Higher-Order Functions` is one of them. 

In this post we will discuss `map()`, `filter()` and `reduce()` that are some of the most well-known and easy to use Higher-Order Functions.


## What Is Map?

>The `map()` method creates a **new array** with the results of **calling a provided function on every element in the calling array**.


Let's say that we want to create a new array that contains the double values of the numbers array.

A way to do it is to create the function double and call it for every element in the forEach.


## Map written with a forEach

```js
const numbers = [1, 2, 3];
const result = [];

const double = (number) => {
    return number * 2;
};

// Iterate over an array
numbers.forEach((number) => {
  result.push(double(number)); 
})

// [2 4 6]
console.log(result);
```


And this is where `map` comes into play! Instead of calling the function manually, we can pass the function to map and javascript will call the function on every element for us! 

## Map written without a forEach
```js
const numbers = [1, 2, 3];

const double = (number) => {
  return number * 2;
};

const result = numbers.map(double);

//[2,4,6]
console.log(result);
```

## Now let's see some other examples that we can use map

In the example below we create a new array using map that contains the full name of each person.

```js
const people = [{
    first_name: "Michael",
    last_name: "Jordan"
}, {
    first_name: "LeBron",
    last_name: "James"
}, {
    first_name: "Stephen",
    last_name: "Curry"
}];

const fullNames = people.map((person) => {
    return `${person.first_name} ${person.last_name}`;
});

// [ 'Michael Jordan', 'LeBron James', 'Stephen Curry' ]
console.log(fullNames);
```
In the example below we create a new array that contains the first two letters of each day.

```js
const days = [
    'Sunday',
    'Monday',
    'Tuesday',
    'Wednesday',
    'Thursday',
    'Friday',
    'Saturday'
];

const newDays = days.map((day) => {
    return day.substring(0,2);
});

// [ 'Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa' ]
console.log(newDays);
```

## When should you use a map?

1. When you want to create a new array of the **same** length as the original array.
2. When you want to transform an array of one thing into an array of another thing.

---

## What Is Filter?


>The `filter()` method creates a new array with all elements that pass the test implemented by the provided function. 
* The call to `filter()` will return a new array.
* The callback function used with `filter` should either return `true` or `false`.
  * `true` if the current element should appear in the new array.
  * `false` if the current element should NOT appear in the new array.

Let's say that we want to create a new array that contains the even numbers of the numbers array.

A way to do it is to create the function isEven to check if the number is even or not and call it for every element in the forEach.

## Filter written with a forEach

```js
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const evenNumbers = [];

const isEven = (number) => {
    return number % 2 === 0;
  };

// 2. Iterate over an array
numbers.forEach((number) => {
  if (isEven(number)) {
    evenNumbers.push(number);
  }
});

// [ 2, 4, 6, 8, 10 ]
console.log(evenNumbers);
```

## Filter written without a forEach

```js
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

const isEven = (number) => {
  return number % 2 === 0;
};

const evenNumbers = numbers.filter(isEven);

// [ 2, 4, 6, 8, 10 ]
console.log(evenNumbers);
```

## <br/><br/>Now let's see some other examples, that we can use filter <br/>

In the example below we create a new array that contains the people that their first_name has six or less characters.

```js
const people = [{
    first_name: "Michael",
    last_name: "Jordan"
}, {
    first_name: "LeBron",
    last_name: "James"
}, {
    first_name: "Stephen",
    last_name: "Curry"
}];


const short = people.filter((person) => {
    return person.first_name.length <= 6;
});

// [ { first_name: 'LeBron', last_name: 'James' } ]
console.log(short);
```


In the example below we have an array that contains the weekly days and we want to create a new array that will contain only the days that the number of their letters is less than 7.

```js
const days = [
  'Sunday',
  'Monday',
  'Tuesday',
  'Wednesday',
  'Thursday',
  'Friday',
  'Saturday'
];
// create a new array with only the days that the length of their characters is less than 7
const shortDays = days.filter(day => {
  return day.length < 7;
});

// [ 'Sunday', 'Monday', 'Friday' ]
console.log(shortDays);
```

## When to use Filter:

* When you want a new array of a different length, based on some condition that only some elements in the array satisfy.

---

## What Is Reduce?

>The `reduce()` method applies a function against an accumulator and each element in the array (from left to right) to reduce it to a single value. The accumulator can be anything (integer, string, object, etc.) and must be instantiated or passed when calling reduce().

* The call to `reduce()` will return a single value.
* The callback function used with `reduce` will get passed the accumulator value and an element in the array.
  * The accumulator value is the value returned from the last call to the callback function.
  * The callback function should always return a value to be used in the next callback.
* The third argument to the `reduce()` function is the starting value for the accumulator.

Let's say that we want to calculate the sum of the numbers array.

## Reduce written with a forEach
```js
const numbers = [1,2,3,4,5,6];
let sum = 0;

// Iterate over the array
numbers.forEach((number) => {
    sum +=  number;
});

// 21
console.log(sum);
```
## Reduce written without a forEach

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

// Iterate over the array
const sum = numbers.reduce((sum, number) => {
    sum += number;
    return sum; // Return the accumulator
}, 0);  // Initialize accumulator variable

// 21
console.log(sum);
```
Now let's see some other examples, that we can use reduce.

In the example below we create a new object that contains as a key the name of the stock and as a value the frequency of the stock.

```js
const stocks = ['TSLA', 'PLTR', 'TSLA', 'AAPL', 'PLTR', 'TSLA'];

const result = stocks.reduce((stockFreq, stock) => {
    if(stockFreq.hasOwnProperty(stock)) {
        stockFreq[stock]++;
    } else {
        stockFreq[stock] = 1;
    }

    return stockFreq;
}, {});

// { TSLA: 3, PLTR: 2, AAPL: 1 }
console.log(result);
```
In the example below we create a new string that contains the first two letters of each day.

```js
const days = [
    'Sunday',
    'Monday',
    'Tuesday',
    'Wednesday',
    'Thursday',
    'Friday',
    'Saturday'
];

const newDay = days.reduce((buffer ,day) => {
    buffer += day.substring(0,2);
    return buffer;
}, "");

// SuMoTuWeThFrSa
console.log(newDay);
```

## Resources

* [MDN: Array.prototype.map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)
* [MDN: Array.prototype.filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter)
* [MDN: Array.prototype.reduce](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce)
* [ Coding Garden Video](https://www.youtube.com/watch?v=0R6eX8JrFBA)