The method map
The method map is an array method that allows you to perform operations on the elements of an array. Imagine you have an array like this :
const nums = [2, 4, 3, 11, 19];
and for one reason or another, you want to get the double of each element of the array in another array. You would want to use a loop like this :
const nums2 = []
for (let n of nums) {
nums2.push(n*2);
}
console.log(nums2) // [4, 8, 6, 11, 38]
The method map allows you to do something like that. It creates a new array (like num2) and push
in the new array, the output of the function set at callback.
This callback is invoked for each element of the array. This function is like a helper that works with each item in the array, and it gets the current item as a special piece of information to use while doing its job. Let's create a function that multiplies a number by 2.
// Normal function
function multiply(n) {
return n * 2;
}
// Arrow function
const multiply = (n) => {
return n * 2;
}
This function multiplies by 2, the number n
and then returns the double of n.
Let's use our callback with the method map :
const nums = [2, 4, 3, 11, 19];
// multiply by 2 the number n
const multiply = (n) => {
return n * 2;
}
const nums2 = nums.map(multiply);
console.log(nums2) // [4, 8, 6, 22, 38]
What Happened? The method map
creates a new empty array. For each element n of nums
, it invokes our function multiply(n)
and fills the new empty array with the output of multiply(n)
. Finally, the function map sends the new filled array.
map
with an anonymous function(a function without a name) like this: nums.map( (n) => { return n * 2} )multiply
. When we send a callback function as a parameter, we use it as a simple variable so we add neither the parenthesis "()" nor the arguments because we do not want to invoke/use its content now, it will be called later by the method map
with the right arguments.Don't forget, your callback must return a value, it is the value with which the new array will be filled(here n * 2) where n represents the value of the first array.
It is not an obligation that the new table contains the same type of data. For example, you can get an array of strings with an array of numbers. Let's see it together :
const nums = [2, 4, 3, 11, 19];
const myCallback = (n) => {
return "The value received is " + n;
}
const result = nums.map(myCallback)
Let's dig deeper with another exercise. Consider that you have this array...
const stock = [
{ fruit: 'apple', qty: 3 },
{ fruit: 'pineapple', qty: 5 },
{ fruit: 'tangerine', qty: 10 },
{ fruit: 'banana', qty: 12 }
]
but you think that the attribute name 'fruit' is not suitable and you want to replace 'fruit' with 'name'. You want to get this :
const newStock = [
{ name: 'apple', qty: 3 },
{ name: 'pineapple', qty: 5 },
{ name: 'tangerine', qty: 10 },
{ name: 'banana', qty: 12 }
]
First, try to do it by yourself before seeing the result.
Indices: Each element of the array is an object. So, the parameter of your callback will be: { name: namex, qty: quantityx }
.
Let's correct the previous exercise. I hope that you try to do it yourself before looking at this correction. And don't worry if you can't do it, it's by dint of coding that you become a programmer ๐.
const stock = [
{ fruit: 'apple', qty: 3 },
{ fruit: 'pineapple', qty: 5 },
{ fruit: 'tangerine', qty: 10 },
{ fruit: 'banana', qty: 12 }
]
const getAnotherObject = (o) => {
return { name: o.name, qty: o.qty };
}
const newStock = stock.map(getAnotherObject);
console.log(newStock)
Let's crack this code. First, you have your array stock with the bad attribute name('fruit'). Then, the function getAnotherObject
will be invoked for each element in stock
. For each call, the o parameter of the function will be set to an object with two attributes (fruit
and qty
). The callback will return another object with a new attribute(name
and qty
) whose value is exactly the value of the current element(the parameter o). The method map will return an array with the same value but with name
in place of fruit
.
Before we part ways, I would like to emphasize the fact that your callback can take up to three parameters.
const callback = (currentValue, currentIndex, array) => {}
These params are equivalent to these variables in the following code :
const array = [2, 6, 10, 7, 19];
let currentIndex;
for (currentIndex = 0; currentIndex < array.length; currentIndex++) {
let currentValue = array[currentIndex];
}
// or
while (currentIndex < array.length) {
let currentValue = array[currentIndex];
}
currentValue - You already know it, it is the parameter we have worked with so far,
currentIndex - The position of the current element in the array,
array - The array you are mapping.
A last exercise to understand the new parameters. Consider this array :
const nums = [2, 9, 18, 15, 7, 4, 6]
Your mission if you accept it, is to get a new array of objects which will tell us if the number at index i is even or not. Each item of the array is an object with 2 attributes :
index - the index of the item,
even - a boolean with the value true if the item is even, false else.
So you should have this :
const newArray = [
{index: 0, even: true}, // the number at index 0 (2) is even
{index: 1, even: false}, // the number at index 1 (9) is not even
{index: 2, even: true}, // the number at index 2 (18) is even
{index: 3, even: false}, // the number at index 3 (15) is not even
{index: 4, even: false}, // the number at index 4 (7) is not even
{index: 5, even: true}, // the number at index 5 (4) is even
{index: 6, even: true} // the number at index 6 (6) is even
];
Ready? Let's correct it :
const nums = [2, 9, 18, 15, 7, 4, 6]
const getNewArray = () => {
return {}
}
const newArray = nums.map(getNewArray)
For now, our newArray contains seven empty objects because getNewArray
returns an empty object for each element in nums
:
console.log(newArray);
/*
[
{},
{},
{},
{},
{},
{},
{}
]
*/
Our callback should return for each element its index, and true or false if the current value is even or not. So, the callback will look like this:
const getNewArray = (currentValue) => {
// i is the index we of the item
// iseven = true if the item is even or not
return {index: i, even: iseven}
}
index: how can we get the index i ๐. Yes, with the second parameter of the callback:
currentIndex
๐;iseven: a number is even if there is no remainder after dividing this number by 2. So:
if (currentValue % 2 == 0) {
iseven = true;
} else {
iseven = false;
}
// or shorter,
// currentValue % 2 == 0 will already return true or false
iseven = currentValue % 2 == 0;
Let's see now our callback function :
const getNewArray = (currentValue, currentIndex, array) => {
return {index: currentIndex, even: currentValue % 2 == 0}
}
The complete code:
const nums = [2, 9, 18, 15, 7, 4, 6]
const getNewArray = (currentValue, currentIndex, array) => {
return {index: currentIndex, even: currentValue % 2 == 0}
}
const newArray = nums.map(getNewArray)
console.log(newArray);
The result:
const newArray = [
{index: 0, even: true},
{index: 1, even: false},
{index: 2, even: true},
{index: 3, even: false},
{index: 4, even: false},
{index: 5, even: true},
{index: 6, even: true}
];
const getNewArray = (number, i, array)
or as we don't use array
, you can ignore it : const getNewArray = (number, i)
That's it, we're done with the method map
, I'll see you in the next chapter to implement our own version of this method.
Subscribe to my newsletter
Read articles from Rayane TOKO directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Rayane TOKO
Rayane TOKO
๐จโ๐ป Computer Scientist | ๐ Physicist Enthusiast ๐ก Always exploring new technologies and seeking to bridge the gap between science and technology.