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
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:
- the current item in the array
- the array index of the current item
- 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
}
];
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' ]
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' ]
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' ]
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' ]
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;
};
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.
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
const words = ['Python', 'Javascript', 'Go', 'Java', 'PHP', 'Ruby'];
const result = words.filter(word => word.length < 8);
console.log(result);
Using forEach
, we'd write:
const difficult_tasks = [];
tasks.forEach(function (task) {
if (task.duration >= 120) {
difficult_tasks.push(task);
}
});
console.log(difficult_tasks)
With filter
, we can simply write:
const difficult_tasks = tasks.filter((task) => task.duration >= 120 );
console.log(difficult_tasks)
- avoid mutating an array inside a
forEach
orfor
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
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
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
If we take it step by step, it looks like this:
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
Top comments (0)