JavaScript Array Transformation: .map(), .filter(), and .reduce()

Introduction


As a web developer, it is crucial to master the tools at our disposal to optimize our code and make our applications more efficient. The .map(), .filter(), and .reduce() methods in JavaScript are powerful tools for processing data arrays and simplifying our developments.

These methods are also very useful for solving algorithms on sites such as CodinGame or Codewars! (If you want you can follow my Codewars profile 👈)

We will therefore examine in detail each of these methods, their uses with some examples, and also the performance in the conclusion of this article.

 

The .map() method


The .map() method allows to transform each element of an array into another element, using a specified transformation function.
It is very important to note that this function does not modify the original array, but returns a new array with the transformed elements.
For example, if we have a array of numbers [1, 2, 3, 4, 5] and we want to get an array with the square of each number, we could use the .map() method as follows:
 

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

let squaredNumbers = numbers.map(function(number) {
  return number * number;
});

console.log(squaredNumbers); // [1, 4, 9, 16, 25]


By using an arrow function, the mapping can be simplified to a single line:
 

let squaredNumbers = numbers.map(n => n * n);


Here is another more real and concrete example: We have an array of integers representing cents (we will take the euro as currency) and we want to map these values to a readable price for the "fr-FR" localization.
 

const cents = [3000, 20099, 49, 8449];

const prices = cents.map(cent => (cent / 100).toLocaleString("fr-FR", {style: "currency", currency: "EUR"})); 

console.log(prices) // [ "30,00 €", "200,99 €", "0,49 €", "84,49 €" ]


 

The .filter() method


The .filter() method allows to filter the elements of an array based on a specified condition. This method takes a function which defines the filtering condition, and returns a new array containing only the elements that validate this condition.
For example, if we have an array of weather data objects with date and temperature properties and we want to extract all objects with a temperature greater than or equal to 35 degrees Celsius, we could use .filter() as follows:
 

const weatherData = [
  { date: '01-01-2021', temperature: 30 },
  { date: '01-02-2021', temperature: 35 },
  { date: '01-03-2021', temperature: 40 },
  { date: '01-04-2021', temperature: 38 },
];

const hotDays = weatherData.filter(function(day) {
  return day.temperature >= 35;
});

console.log(`The hot days are: ${hotDays.map(day => day.date)}`); 
// The hot days are: 01-02-2021,01-03-2021,01-04-2021


By using an arrow function, the filtering can be simplified to a single line:
 

const hotDays = weatherData.filter(day => day.temperature >= 35);


 

The .reduce() method


The .reduce() function allows to reduce an array to a single value, using a specified reduction function.
This method takes as parameter a function that defines how the elements of the array are reduced, and an initial value that is used to start the reduction. The reduction function is called for each element of the array, with two parameters: the accumulator, which is the current value of the reduction, and the current element, which is the element currently being processed.
As for the .map() and .filter() methods, the .reduce() method is not a mutator method and therefore simply returns a new array.

Let's take the following example: We have an array of numbers [1, 2, 3, 4, 5] and we want to calculate the sum of all the numbers, we could use .reduce() as follows:
 

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

let sum = numbers.reduce(function(accumulator, currentValue) {
  return accumulator + currentValue;
}, 0);

console.log(sum); // 15


By using an arrow function, the reduction can be simplified to a single line:
 

let sum = numbers.reduce((acc, val) => acc + val, 0);


Here is another more real and concrete example: We want to extract all the video game categories from an array of objects, so we will reduce the array of objects to return a new array containing the categories while avoiding duplication.
 

const videoGames = [
  {
    name: 'The Binding of Isaac',
    category: 'Roguelike'
  },
  {
    name: 'Overwatch 2',
    category: 'FPS'
  },
  {
    name: 'Vampire Survivors',
    category: 'Roguelike'
  },
  {
    name: 'Valorant',
    category: 'FPS'
  },
  {
    name: 'The Legend Of Zelda: Tears of the Kingdom',
    category: 'Adventure'
  }
];

const categories = videoGames.reduce((acc, val) => acc.includes(val.category) ? acc : acc.concat(val.category), []);

console.log(categories) // [ "Roguelike", "FPS", "Adventure" ]


The .reduce() method is very useful and can be used in many cases, such as calculating statistics on data, merging multiple tables into one, or even creating new objects.


 

Performances & Conclusion


The .map(), .filter(), and .reduce() methods in JavaScript are powerful tools for processing data arrays and simplifying our developments. By using these methods, you can write clearer and more efficient codes, and you can also solve problems in a more elegant way!

However, these methods are generally slower than for or while loops for tasks that require direct access to a specific element in a collection or complex loop logic because they iterate through all elements in the collection, even if only a specific element is needed.
For example, if you need to access a single specific element in a collection, it would be more efficient to use a for or while loop to iterate through the collection until you find the desired element rather than using a method like .filter() that will iterate through all elements in the collection.

Furthermore, if you need to implement complex loop logic, such as nested conditions or loop jumps, it would be easier and more efficient to use a for or while loop to code this logic rather than trying to code it using the .filter(), .map(), and .reduce() methods.


In summary, these methods are quite performant when used without being diverted from their main use, namely mapping, filtering, and reducing, as they use native implementation in JavaScript to process arrays.
However, they can be slower than loops for or while for very large arrays or for very complex operations. Therefore, it's important to use them judiciously.

 


Discover related posts

0 comment