DEV Community

Cover image for Understanding the .map(), .filter() and .reduce() array methods in Javascript.
Samuel Jarvis
Samuel Jarvis

Posted on

Understanding the .map(), .filter() and .reduce() array methods in Javascript.

Arrays are one of the most used data structures in Javascript, from storing basic data in our code to getting results from API calls. As Javascript developers were always working with arrays and carrying out some form of operation on them.

The .map(), .reduce() and .filter() are some of the lesser-known array methods released in ES6, that uses a more functional and cleaner approach to carry out array operations.

In this article, weโ€™ll be taking a detailed look at how these array methods work and how we can use them to carry out some basic operations.

Overview

First a brief look at what these array methods do.

The .map() method returns a new array where each element have gone through an operation of some kind.

The .filter() method returns a new array containing only array elements that passed a specific condition.

The .reduce() method reduces all the elements in the original to a single value.

These array methods are Higher Order Functions, meaning they take callback functions as parameters.

The .map() method

The .map() method returns a new array that contains the result of applying an operation on each of the original array elements.

The .map method accepts a callback function as a parameter and an important parameter for the callback function is the element parameter, the element parameter is processed by the callback function and returned an element to the new array.

Syntax for the .map() method

Array.map(function (element) {
    //operation on element
})

//using arrow function
Array.map(element => {
    //operation on element
})
Enter fullscreen mode Exit fullscreen mode

Using the .map() method

let numbers = [24, 11, 8, 13]

const double = numbers.map(number=> score * 2)
console.log(double) 
// outputs [ 48, 22, 16, 26 ]
Enter fullscreen mode Exit fullscreen mode

When we run the code above. The .map() function loops through the numbers array, assigns the current element in iteration as number, carries out the operation number * 2, and then finally inserts this new value to the new array.

Note that the .map() method will always return an array of the same length as the original array.

For the rest of this tutorial, we'll be working with an array of objects, that contains the name, occupation and score of a group of employees.

const employees = [
  {
    name: "Peter",
    score: 25,
    occupation: "Engineer"
  },
  {
    name: "Judy",
    score: 30,
    occupation: "Banker"
  },
  {
    name: "Jarvis",
    score: 40,
    occupation: "Doctor"
  },
  {
    name: "Paul",
    score: 65,
    occupation: "Engineer"
  }
]
Enter fullscreen mode Exit fullscreen mode

The .map() method can also be used to extract specific data from an array
With the .map() method, we can get the names of all the employees to a new array.

const names = employees.map(person => person.name)
console.log(names) 
//returns ["Peter","Judy","Jarvis","Paul"]

Enter fullscreen mode Exit fullscreen mode

More callback parameters

The .map() callback function can take more parameters that you might find useful when carrying out array operations.

Array.map((element, index, array) {operation})

The element parameter is used to access the current element in iteration.

The index returns the index of the current element in iteration

the array returns the complete original array.

I personally haven't seen any use case for the array parameter. If you have seen please comment below.

The .filter() Method

The .filter() returns a new array containing only elements that passed the condition passed in the callback function.

Syntax for the .filter() method

Array.filter(element => {
    //condition
})
Enter fullscreen mode Exit fullscreen mode
let numbers = [24, 11, 8, 13]

const filter =  numbers.filter(number => number > 10)
console.log(filter)  
// output [24,11,13]
Enter fullscreen mode Exit fullscreen mode

When we run the code above the .filter() method loops through the numbers array, and checks if the current number is greater than 10, if true the number is added to the new array.

Using the .filter() method

We can use the .filter() method to get the array of employees who are engineers from our data above.

const allEngineers = people.filter(person => person.occupation === "Engineer")
console.log(allEngineers)
//Outputs 

[
  {
    name: "Peter",
    score: 25,
    occupation: "Engineer"
  },
{
    name: "Paul",
    score: 65,
    occupation: "Engineer"
  }
]
Enter fullscreen mode Exit fullscreen mode

Optional callback parameters

The .filter() callback function just like the .map() can also take more than just the element parameter as an argument and they also serve the same purpose.

Array.filter((element, index, array) {condition})  
Enter fullscreen mode Exit fullscreen mode

The .reduce() method.

The .reduce() method is used to combine all the elements in an array to get a value. It evaluates all of the elements in the array to return a single value.

The .reduce() method is a little more complicated than the other two mentioned above because its callback function requires a specific parameter known as the โ€œaccumulatorโ€ which holds the total value during the operation and returns it after the operation is completed. This "accumulator" parameter is used in the reducer function.

Syntax for .reduce() method

Array.reduce((accumulator, element) {
    //reducer
}, initial value)
Enter fullscreen mode Exit fullscreen mode

Using the .reduce method to get the sum of numbers.

let numbers= [24, 11, 8, 13]

const sum =  numbers.reduce((sum, number) => {
  return sum + number
}, 0)

console.log(sum)  
// outputs 56
Enter fullscreen mode Exit fullscreen mode

When the code above runs the .reduce() method first set the value of sum to 0 which was provided as the initial value and then loops through the array, on every iteration, it adds number to the value of sum, and after the last element returns sum which in our case is 56.

While the initial value might be optional it's always advisable to specify it, to avoid getting a TypeError in the case of an empty array. We get the error message below.

Uncaught TypeError: Reduce of empty array with no initial value

Chaining Methods

One of the pros of using these array methods is the ability to chain them. Since unlike the .forEach() method these array methods return a new array, we can chain them to get a combo method.

Chaining is combining array methods to perform operations on them and get a final return value.

Using chaining we can get the names of employees who scored above 35.

const passed= people.filter(person => person.score > 35)
  .map(person => person.name)

console.log(passed)
 // outputs ["Judy","Jarvis","Paul"]
Enter fullscreen mode Exit fullscreen mode

In the code above the .filter() operation is carried out first on the array which returns an array of employees whose score is above 35 then the .map() method returns their name as the final value of the operation.

We can also get the sum of the scores of engineers only.

const engineersScore= people.filter(person => person.occupation === "Engineer") //return an array of engineers only
    .map(person => person.score) //returns the array of engineers score
    .reduce((sum, element) => sum + element) //sums up the score.

console.log(engineersScore)
//outputs 90
Enter fullscreen mode Exit fullscreen mode

Conclusion

The best way to master new concepts is by using them. Try using these methods in place of the .forEach() when possible.

Feel free to comment below if you have any feedback and please share with other Javascript developers.

Let's Connect on Twitter

Resource I used

MDN

Top comments (10)

Collapse
 
frankwisniewski profile image
Frank Wisniewski
let numbers = [24, 11, 8, 13]

const double = numbers.map(number=> score * 2)
console.log(newScores) 
Enter fullscreen mode Exit fullscreen mode

score and newScores ??

try this:

let numbers = [24, 11, 8, 13]

const double = numbers.map(number=> number * 2)
console.log(double) 
Enter fullscreen mode Exit fullscreen mode

next:

let numbers= [24, 11, 8, 13]

const sum =  numbers.reduce((sum, number) => {
  return sum + score
}, 0)

console.log(sum)
Enter fullscreen mode Exit fullscreen mode

score ??

Collapse
 
samjarvis244 profile image
Samuel Jarvis • Edited

Thanks a lot. I made some changes to the varible names and didn't change it everywhere.
I'll edit these these. Thanks

Collapse
 
htho profile image
Hauke T.

I always have to think hard before I use reduce, thats why I checked your example. Nice work.

Please Double check your code examples. Your example for the syntax of the reduce method is (syntactically) incorrect. You probably wanted to write "initialValue" instead of "inital value".

Collapse
 
konoplitskii profile image
Sergey

My favorite methods that I use in my work. Thanks for the article, it was useful to repeat. ๐Ÿ™‚

Collapse
 
jonrandy profile image
Jon Randy ๐ŸŽ–๏ธ • Edited

I wish people would stop referring to all functions that are passed in to other functions as 'callback functions'. It gives the misleading impression that they are somehow different or special in some way, when in fact they are just plain, ordinary functions. Giving them a fancy name just introduces unnecessary confusion to new developers, where there need not be any.

It only really makes sense to refer to them as 'callback' functions when they are passed into a function that performs an asynchronous task which will finish at some indeterminate time in the future - at which point, the function will be "called back" to tell you it's done. That is where the name comes from.

Collapse
 
frankwisniewski profile image
Frank Wisniewski • Edited
Collapse
 
jonrandy profile image
Jon Randy ๐ŸŽ–๏ธ • Edited

Yeah, definitions vary... but I do feel it introduces unnecessary confusion - especially when not explained clearly (which I am indeed a little guilty of above). I see people refer to passed functions as 'callbacks' even when they are not called - i.e. in a function that wraps the passed function then returns the wrapped version - so confusion clearly exists. It is not as simple as 'every function passed to another function is a callback function', which I've heard variations of from many junior devs / interviewees.

The key part in the Wikipedia definition is:

that code is expected to call back (execute) the callback function as part of its job

Thread Thread
 
frankwisniewski profile image
Frank Wisniewski

for me it's just a function. Some see it differently. It's getting on my nerves that filter, map and reduce are talked about here every few days.....

Thread Thread
 
jonrandy profile image
Jon Randy ๐ŸŽ–๏ธ • Edited

Haha, yep. Dev should introduce a feature when you post to check if you're effectively reposting content from existing documentation, and attempt to discourage you from doing so.

Collapse
 
dev_nv profile image
Noel V Abraham

It's super helpful bro๐Ÿ˜‡