DEV Community

Bipon Biswas
Bipon Biswas

Posted on

Map, Filter, and Reduce in JavaScript

Map, Filter, and Reduce in JavaScript

The syntax for map is shown below.

array.map(function(currentValue, index, arr), thisValue)
// return element for newArray, after executing something
Enter fullscreen mode Exit fullscreen mode

The map() method creates a new array and performs a function on each array element

Under the hood, map passes three arguments to your callback:

  1. the current item in the array
  2. the array index of the current item
  3. the entire array you called map on

Let's look at some code

map in Example

// Durations are in minutes 
const tasks = [
  {
    'name'     : 'Write for Learning',
    'duration' : 120
  },
  {
    'name'     : 'Work out',
    'duration' : 60
  },
  {
    'name'     : 'Watching Movie',
    'duration' : 60
  }
];
Enter fullscreen mode Exit fullscreen mode

Let's say we want to create a new array with just the name of each task, so we can take a look at everything we've done today. Using a for loop, we'd write something like this:

const task_names = [];
for (let i = 0; i < tasks.length; i +=1){
    task_names.push(tasks[i].name)
}
console.log(task_names) // [ 'Write for Learning', 'Work out', 'Watching Movie' ]
Enter fullscreen mode Exit fullscreen mode

Map

JavaScript also offers a forEach loop. It functions like a for loop, but manages all the messiness of checking our loop index against the array length for us:

const task_names = [];

tasks.forEach(function (task) {
    task_names.push(task.name);    
});

console.log(task_names) // [ 'Write for Learning', 'Work out', 'Watching Movie' ]
Enter fullscreen mode Exit fullscreen mode

Map

Using map, we can simply write:

const task_names = tasks.map(function (task, index, array) {
    return task.name; 
});
console.log(task_names) // [ 'Write for Learning', 'Work out', 'Watching Movie' ]
Enter fullscreen mode Exit fullscreen mode

An even more succinct way of writing map in modern JavaScript is with arrow functions

const task_names = tasks.map(task => task.name)

console.log(task_names) // [ 'Write for Learning', 'Work out', 'Watching Movie' ]
Enter fullscreen mode Exit fullscreen mode

Arrow functions are a short form for one-line functions that just have a return statement.

let map = function (array, callback) {
  const new_array = [];

  array.forEach(function (element, index, array) {
    new_array.push(callback(element));
  });

  return new_array;
};
Enter fullscreen mode Exit fullscreen mode

This code accepts an array and a callback function as arguments. It then creates a new array, executes the callback on each element on the array we passed in, pushes the results into the new array, and returns the new array.

More Details

Filter
It does exactly what it sounds like: It takes an array and filters out unwanted elements.

The syntax for filter is:

array.filter(function(currentValue, index, arr), thisValue)
// return element for newArray, if true
Enter fullscreen mode Exit fullscreen mode
const words = ['Python', 'Javascript', 'Go', 'Java', 'PHP', 'Ruby'];
const result = words.filter(word => word.length < 8);
console.log(result);
Enter fullscreen mode Exit fullscreen mode

Filter

Using forEach, we'd write:

const difficult_tasks = [];

tasks.forEach(function (task) {
    if (task.duration >= 120) {
        difficult_tasks.push(task);
    }
});
console.log(difficult_tasks)
Enter fullscreen mode Exit fullscreen mode

forEach

With filter, we can simply write:

const difficult_tasks = tasks.filter((task) => task.duration >= 120 );
console.log(difficult_tasks)
Enter fullscreen mode Exit fullscreen mode

forEach

  • avoid mutating an array inside a forEach or for loop
  • assign its result directly to a new variable, rather than push into an array we defined elsewhere

Reduce
map creates a new array by transforming every element in an array individually. filter creates a new array by removing elements. reduce, on the other hand, takes all of the elements in an array and reduces them into a single value.

reduce in Practice

let numbers = [1, 2, 3, 4, 5],
    total = 0;

numbers.forEach(function (number) {
    total += number;
});
console.log(total); // 15
Enter fullscreen mode Exit fullscreen mode

While this isn't a bad use case for forEach, reduce still has the advantage of allowing us to avoid mutation. With reduce, we would write:

const total = [1, 2, 3, 4, 5].reduce(function (previous, current) {
    return previous + current;
}, 0);
console.log(total); // 15
Enter fullscreen mode Exit fullscreen mode

First, we call reduce on our list of numbers. We pass it a callback, which accepts the previous value and current value as arguments, and returns the result of adding them together. Since we passed 0 as a second argument to reduce, it'll use that as the value of previous on the first iteration.

With arrow functions, we would write it like this:

const total = [1, 2, 3, 4, 5].reduce((previous, current) => previous+current),0;
console.log(total) // 15
Enter fullscreen mode Exit fullscreen mode

If we take it step by step, it looks like this:
Reduce Iteration
Another example

let num1 = [2, 3, 4, 5, 6, 7];
let num4 = num1.reduce(sum)
         function sum(total, value){
             return total + value;
         }
document.getElementById("demo").innerHTML = num4; // 27
Enter fullscreen mode Exit fullscreen mode

Top comments (0)