Array.reduce() en JavaScript : ramener un tableau à une seule valeur

reduce parcourt un tableau en transportant un accumulateur : la valeur initiale, le regroupement de données et les cas où il vaut mieux s'abstenir.
3 min de lecture
Believemy logo

Additionner des montants, compter des occurrences, regrouper des lignes par pays : trois opérations différentes qui partagent la même forme, un tableau en entrée et une seule valeur en sortie.

reduce est la méthode qui décrit cette forme, et la plus redoutée du lot parce qu'elle demande de nommer deux choses au lieu d'une.


Définition

reduce parcourt un Array (tableau) en transportant une valeur d'un tour à l'autre, l'accumulateur. À chaque élément, la fonction reçoit cet accumulateur et l'élément, et renvoie le nouvel accumulateur. Le dernier renvoyé est le résultat.

JAVASCRIPT
const montants = [12, 30, 8];

const total = montants.reduce((somme, m) => somme + m, 0);
console.log(total);   // 50

Le 0 final est la valeur de départ de l'accumulateur, souvent prise pour un détail. Elle décide en réalité du type du résultat : 0 pour un nombre, "" pour une chaîne, {} pour un objet, [] pour un tableau.


La valeur initiale n'est pas facultative

Elle peut être omise, et le premier élément sert alors d'accumulateur. Sur un tableau vide, il n'y a plus rien à prendre.

JAVASCRIPT
try {
  [].reduce((a, b) => a + b);
} catch (err) {
  console.log(err.name);      // TypeError
  console.log(err.message);   // Reduce of empty array with no initial value
}

console.log([].reduce((a, b) => a + b, 0));   // 0

Le tableau vide n'est pas un cas rare : c'est ce que rend un Array.filter() qui n'a rien trouvé, ou une requête sans résultat. Écrire la valeur initiale coûte trois caractères et supprime la panne.


Regrouper des données

C'est l'usage où reduce devance nettement une boucle, parce que la structure de sortie est déclarée à la fin de la ligne.

JAVASCRIPT
const ventes = [
  { pays: "FR", montant: 40 },
  { pays: "BE", montant: 15 },
  { pays: "FR", montant: 60 },
];

const parPays = ventes.reduce((acc, v) => {
  acc[v.pays] = (acc[v.pays] ?? 0) + v.montant;
  return acc;
}, {});

console.log(parPays);   // { FR: 100, BE: 15 }
Attention

Ne recréez pas l'accumulateur à chaque tour avec Spread (...), comme dans reduce((acc, v) => ({ ...acc, [v.pays]: v.montant }), {}). Le coût devient proportionnel au carré du nombre d'éléments, et la ligne se lit à peine mieux. Modifiez l'accumulateur puis renvoyez-le.


Questions fréquentes

Question

Quand faut-il préférer une boucle ?

Dès que la fonction dépasse cinq ou six lignes, ou qu'elle doit s'arrêter avant la fin. reduce parcourt toujours tout le tableau, sans échappatoire. Une boucle for avec un break dit alors la même chose plus clairement.

Question

reduce peut-il remplacer Array.map() et filter ?

Techniquement oui, en un seul parcours. En pratique le gain de vitesse est faible et le code devient nettement moins lisible : le nom map annonce une transformation, un reduce n'annonce rien. Gardez-le pour ce que les autres ne font pas.

Question

À quoi sert reduceRight ?

À parcourir le tableau de la fin vers le début, avec la même signature. Le cas réel est la composition de fonctions, où l'ordre d'application compte. Pour une somme ou un comptage, le sens de parcours ne change rien au résultat.

Termes connexes

Découvrez notre glossaire JavaScript

Tous les mots de JavaScript expliqués simplement : mots-clés, objets natifs, méthodes, erreurs et concepts. Définitions claires et exemples qui tournent, pour apprendre et pour se dépanner.

Partager cet article

Tu veux nous aider ? Fais un lien vers cet article sur tes réseaux ou encore mieux : sur ton site, dans un article ou dans ta newsletter.