.map(), .reduce() et .filter(): incontournables en Javascript

Les array en javascript ont plusieurs méthodes extrêmement pratiques, que vous serez probablement amené à utiliser : map(), reduce() et filter(). Nous allons vous les présenter ici.

Elles appartiennent au prototype des Array, si vous voulez plus d’information sur ce point, vous pouvez consulter notre article sur les prototypes.

La méthode .map() en javascript

La méthode map() sert à transformer chaque élément d’un tableau en appliquant une fonction. Prenons un exemple tiré de mon programme de visualisation de contenu:

<select
   value={queryFilter}
   onChange={(e) => dispatch(setQueryFilter(e.target.value))}
>
  <option value="">None</option>
  {availableQueries.map((query, index) => (
  <option key={index} value={query}>
     {query}
     </option>
  ))}
</select>

Il s’agit d’une liste d’options permettant de définir un filtre. La difficulté est qu’il faut mettre à jour les options disponibles en fonction de ce qui est renseigné par les autres filtres. Les options disponibles sont enregistrées dans l’array « availableQueries« . Ce qui nous intéresse est qu’il faut ensuite qu’elles s’affichent, ce qu’on arrive à faire avec la méthode map:

  • Pour chaque query, un élément <option> est créé avec une key unique et une value.
    • key={index} attribue à l’élément une clé unique basée sur son indice.
    • value={query} fixe la valeur de l’option à la valeur actuelle de query.
    • {query} affiche la valeur de query comme texte visible de l’option.

La méthode .filter() en javascript

Comme dans l’exemple précédent, nous allons prendre un morceau de code de mon application de visualisation de données :

export const queriesOptions = createSelector(
  [
    selectAllData,
    selectPageFilter,
    selectCategoryFilter,
    selectTypeFilter,
    selectMinQueryImpressions,
  ],
  (data, pageFilter, categoryFilter, typeFilter, minImpressions) => {
    if (pageFilter) {
      data = data.filter((row) => row.Page === pageFilter);
    }
    if (categoryFilter) {
      data = data.filter((row) => row.Cat1 === categoryFilter);
    }
    if (typeFilter) {
      data = data.filter((row) => row.Type === typeFilter);
    }
    return [
      ...new Set(
        data
          .filter((row) => row.Impressions >= minImpressions)
          .map((row) => row.Query)
      ),
    ];
  }
);

Ce bloc de code permet d’appliquer successivement les filtres à la données initiale (data) et d’en tirer un tableau filtré. Approfondissons les lignes telles que « data = data.filter((row) => row.Type === typeFilter)« 

  • data = : Réassigne le résultat du filtrage à la variable data. Le tableau original est remplacé par le tableau filtré.
  • data.filter() : Appelle la méthode .filter() sur le tableau data.
  • ((row) => row.Type === typeFilter) : Ceci est la fonction de rappel qui sera exécutée pour chaque élément du tableau data. Chaque row du tableau data est passé à la fonction de rappel. Si row.Type est égal à typeFilter, row est inclus dans le tableau résultant. Ce nouveau tableau filtré remplace ensuite le tableau original data.

On peut se demander: d’accord il y a une vérification de condition, mais où est renseignée sa conséquence ?

C’est qu’en fait la fonction de rappel dans .filter() doit retourner un booléen (true ou false). Celui-ci détermine si l’élément actuel doit être inclus dans le tableau résultant ou non.

La méthode .reduce() en javascript

Reduce est une méthode qui réduit un tableau à une seule valeur. Voici sa syntaxe:

const resultat = tableau.reduce((accumulateur, element, index, array) => { /* ... */ }, valeurInitiale);
  • resultat: La valeur finale de l’accumulateur après avoir parcouru tous les éléments du tableau.
  • tableau: Le tableau sur lequel .reduce() est appelé.
  • accumulateur: La valeur accumulée jusqu’à présent. Commence avec valeurInitiale.
  • element: L’élément actuel du tableau.
  • index: L’index actuel dans le tableau (optionnel).
  • array: Le tableau lui-même (optionnel).

Cette fois-ci, prenons un exemple standard (celui de mon application est un peu complexe):

const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((acc, num) => acc + num, 0);
console.log(sum);

Cela rend 15. Ainsi vous avez additionné les éléments du tableau. Voici le détail:

  1. acc est notre accumulateur. On l’initialise à 0.
  2. num représente chaque nombre dans le tableau numbers.
  3. La fonction .reduce() parcourt chaque élément du tableau.
  4. Pour chaque nombre, elle ajoute sa valeur à acc.
  5. À la fin, acc contient la somme totale, qui est 15 dans cet exemple.

Avec une boucle foreach, cela donnerait:

const numbers = [1, 2, 3, 4, 5];
let sum = 0;
numbers.forEach((num) => {
  sum += num;
});
console.log(sum); // Output: 15

Les fonctions proches

Sort()

Ces fonctions sont proches de sort(). Néanmoins, cette dernière ne renvoie pas un nouveau tableau, mais modifie le tableau sur lequel on itère. Voici un exemple:

const numbers = [10, 5, 8, 1, 7];
numbers.sort((a, b) => a - b);
// Résultat : [1, 5, 7, 8, 10]
numbers.sort((a, b) => b - a);
// résultat : [10, 8, 7, 5, 1]

La syntaxe est très simple : array.sort([fonctionComparaison])

Array est le tableau à trier et fonctionComparaison la logique de tri. cette dernière peut être laissée vide, les éléments sont alors triés en utilisant leur valeur Unicode en tant que chaîne de caractères. La fonction de comparaison doit renvoyer un nombre négatif, positif ou zéro. Cela voudra dire que a doit être placé après, avant ou au même niveau que b.

C’est particulièrement pratique pour trier des objets par rapport à une de leurs propriétés. La fonction de comparaison est alors de la forme (a,b) => a.propriété – b.propriété .

La différence avec foreach

Toutes ces fonctions peuvent être aussi obtenues par une boucle foreach. Leur utilisation rend néanmoins le code plus lisible pour ceux qui connaissent ces méthodes très communes.