[ Web Proxy ]
URL:
Viewing: https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce [Back]  [Original]

Array : mthode reduce() - JavaScript | MDN

Cette page a t traduite partir de l'anglais par la communaut. Vous pouvez contribuer en rejoignant la communaut francophone sur MDN Web Docs.

View in English Always switch to English

Array : mthode reduce()

Baseline Large disponibilit

Cette fonctionnalit est bien tablie et fonctionne sur de nombreux appareils et versions de navigateurs. Elle est disponible sur tous les navigateurs depuis juillet 2015.

La mthode reduce() des instances Array excute une fonction de rappel  de rduction  fournie par l'utilisateurice sur chaque lment du tableau, dans l'ordre, en transmettant la valeur retourne par le calcul prcdent. Le rsultat final de l'excution du rducteur sur tous les lments du tableau est une seule valeur.

La premire fois que la fonction de rappel est excute, il n'y a pas de  valeur retourne par le calcul prcdent . Si elle est fournie, une valeur initiale peut tre utilise la place. Sinon, l'lment du tableau d'index 0 est utilis comme valeur initiale et l'itration commence l'lment suivant (index 1 au lieu de l'index 0).

Dans cet article

Exemple interactif

const array1 = [1, 2, 3, 4];

// 0 + 1 + 2 + 3 + 4
const initialValue = 0;
const sumWithInitial = array1.reduce(
  (accumulator, currentValue) => accumulator + currentValue,
  initialValue,
);

console.log(sumWithInitial);
// Rsultat attendu : 10

Syntaxe

js
reduce(callbackFn)
reduce(callbackFn, initialValue)

Paramtres

callbackFn

La fonction de rappel excuter pour chaque lment du tableau. Sa valeur de retour devient la valeur du paramtre accumulator lors de l'appel suivant de callbackFn. Pour le dernier appel, la valeur de retour devient la valeur retourne par reduce(). La fonction est appele avec les arguments suivants :

accumulator

La valeur rsultant de l'appel prcdent de callbackFn. Lors du premier appel, sa valeur est initialValue si ce dernier est dfini ; sinon, sa valeur est array[0].

currentValue

La valeur de l'lment courant. Lors du premier appel, sa valeur est array[0] si initialValue est dfini ; sinon, sa valeur est array[1].

currentIndex

L'index de currentValue dans le tableau. Lors du premier appel, sa valeur est 0 si initialValue est dfini ; sinon 1.

array

Le tableau sur lequel reduce() a t appel.

initialValue Facultatif

La valeur laquelle accumulator est initialis lors du premier appel de la fonction de rappel. Si initialValue est dfini, callbackFn commence s'excuter avec la premire valeur du tableau comme currentValue. Si initialValue n'est pas dfini, accumulator est initialis la premire valeur du tableau, et callbackFn commence s'excuter avec la seconde valeur du tableau comme currentValue. Dans ce cas, si le tableau est vide (et qu'il n'y a donc pas de premire valeur retourner comme accumulator), une erreur est leve.

Valeur de retour

La valeur qui rsulte de l'excution de la fonction de rappel  de rduction  sur l'ensemble du tableau jusqu' la fin.

Exceptions

TypeError

Leve si le tableau ne contient aucun lment et que la valeur initiale n'est pas dfinie.

Description

La mthode reduce() est une mthode itrative. Elle excute une fonction de rappel  de rduction  sur tous les lments du tableau, dans l'ordre croissant des indices, et les accumule en une seule valeur. chaque itration, la valeur retourne par callbackFn est transmise nouveau callbackFn lors de l'appel suivant en tant qu'accumulator. La dernire valeur de accumulator (c'est--dire la valeur retourne par callbackFn lors de la dernire itration du tableau) devient la valeur retourne par reduce(). Consultez la section mthodes itratives pour plus d'informations sur le fonctionnement gnral de ces mthodes.

callbackFn n'est appele que pour les indices du tableau qui ont des valeurs attribues. Elle n'est pas appele pour les cases vides dans un tableau creux.

Contrairement aux autres mthodes itratives, reduce() n'accepte pas d'argument thisArg. callbackFn est toujours appele avec la valeur undefined pour this, qui est remplace par globalThis si callbackFn n'est pas en mode strict.

reduce() est un concept central de la programmation fonctionnelle : il n'est pas possible d'y modifier une valeur, donc pour accumuler toutes les valeurs d'un tableau, il faut retourner une nouvelle valeur d'accumulateur chaque itration. Cette convention s'applique reduce() en JavaScript : il convient d'utiliser l'oprateur de propagation ou d'autres mthodes de copie pour crer de nouveaux tableaux et objets comme accumulateur, plutt que de modifier l'existant. Si vous dcidez de modifier l'accumulateur au lieu de le copier, veillez toujours retourner l'objet modifi dans la fonction de rappel, sinon l'itration suivante recevra la valeur undefined. Cependant, copier l'accumulateur peut entraner une utilisation accrue de la mmoire et une dgradation des performances : voir Quand ne pas utiliser reduce() pour plus de dtails. Dans ces cas, pour viter de mauvaises performances et un code illisible, il est prfrable d'utiliser une boucle for la place.

La mthode reduce() est gnrique. Elle attend seulement que la valeur de this possde une proprit length et des proprits cls entires.

Cas particuliers

Si le tableau ne contient qu'un seul lment (peu importe sa position) et qu'aucune initialValue n'est fournie, ou si initialValue est fournie mais que le tableau est vide, la valeur unique sera retourne sans appeler callbackFn.

Si initialValue est fournie et que le tableau n'est pas vide, la mthode reduce appellera toujours la fonction de rappel en commenant l'index 0.

Si initialValue n'est pas fournie, la mthode reduce se comporte diffremment selon que la longueur du tableau est suprieure 1, gale 1 ou gale 0, comme illustr dans l'exemple suivant :

js
const getMax = (a, b) => Math.max(a, b);

// la fonction de rappel est appele pour chaque lment du tableau  partir de l'index 0
[1, 100].reduce(getMax, 50); // 100
[50].reduce(getMax, 10); // 50

// la fonction de rappel est appele une fois pour l'lment  l'index 1
[1, 100].reduce(getMax); // 100

// la fonction de rappel n'est pas appele
[50].reduce(getMax); // 50
[].reduce(getMax, 1); // 1

[].reduce(getMax); // TypeError

Exemples

Fonctionnement de reduce() sans valeur initiale

Le code ci-dessous montre ce qu'il se passe si l'on appelle reduce() avec un tableau et sans valeur initiale.

js
const array = [15, 16, 17, 18, 19];

function reducer(accumulator, currentValue, index) {
  const returns = accumulator + currentValue;
  console.log(
    `accumulator: ${accumulator}, currentValue: ${currentValue}, index: ${index}, returns: ${returns}`,
  );
  return returns;
}

array.reduce(reducer);

La fonction de rappel sera appele quatre fois, avec les arguments et valeurs de retour suivants chaque appel :

accumulator currentValue index Valeur retourne
Premier appel 15 16 1 31
Deuxime appel 31 17 2 48
Troisime appel 48 18 3 66
Quatrime appel 66 19 4 85

Le paramtre array ne change jamais pendant le processus : il reste toujours [15, 16, 17, 18, 19]. La valeur retourne par reduce() sera celle du dernier appel de la fonction de rappel (85).

Fonctionnement de reduce() avec une valeur initiale

Ici, on rduit le mme tableau avec le mme algorithme, mais en passant une initialValue de 10 comme second argument reduce() :

js
[15, 16, 17, 18, 19].reduce(
  (accumulator, currentValue) => accumulator + currentValue,
  10,
);

La fonction de rappel sera appele cinq fois, avec les arguments et valeurs de retour suivants chaque appel :

accumulator currentValue index Valeur retourne
Premier appel 10 15 0 25
Deuxime appel 25 16 1 41
Troisime appel 41 17 2 58
Quatrime appel 58 18 3 76
Cinquime appel 76 19 4 95

La valeur retourne par reduce() dans ce cas sera 95.

Additionner les valeurs d'un tableau d'objets

Pour additionner les valeurs contenues dans un tableau d'objets, il faut fournir une initialValue afin que chaque lment soit trait par la fonction.

js
const objects = [{ x: 1 }, { x: 2 }, { x: 3 }];
const sum = objects.reduce(
  (accumulator, currentValue) => accumulator + currentValue.x,
  0,
);

console.log(sum); // 6

Chanage squentiel de fonctions

La fonction pipe prend une squence de fonctions et retourne une nouvelle fonction. Lorsque cette nouvelle fonction est appele avec un argument, la squence de fonctions est appele dans l'ordre, chacune recevant la valeur retourne par la fonction prcdente.

js
const pipe =
  (...functions) =>
  (initialValue) =>
    functions.reduce((acc, fn) => fn(acc), initialValue);

// Briques de base pour la composition
const double = (x) => 2 * x;
const triple = (x) => 3 * x;
const quadruple = (x) => 4 * x;

// Fonctions composes pour multiplier par des valeurs spcifiques
const multiply6 = pipe(double, triple);
const multiply9 = pipe(triple, triple);
const multiply16 = pipe(quadruple, quadruple);
const multiply24 = pipe(double, triple, quadruple);

// Utilisation
multiply6(6); // 36
multiply9(9); // 81
multiply16(16); // 256
multiply24(10); // 240

Excuter des promesses en squence

Le chanage de promesses est essentiellement un chanage de fonctions comme dmontr dans la section prcdente, mais ralis de faon asynchrone.

js
//  comparer avec pipe : fn(acc) devient acc.then(fn),
// et initialValue est garanti d'tre une promesse
const asyncPipe =
  (...functions) =>
  (initialValue) =>
    functions.reduce((acc, fn) => acc.then(fn), Promise.resolve(initialValue));

// Briques de base pour la composition
const p1 = async (a) => a * 5;
const p2 = async (a) => a * 2;
// Les fonctions composes peuvent aussi retourner des non-promesses, car les valeurs sont
// toutes enveloppes dans des promesses au final
const f3 = (a) => a * 3;
const p4 = async (a) => a * 4;

asyncPipe(p1, p2, f3, p4)(10).then(console.log); // 1200

asyncPipe peut aussi tre implment avec async/await, ce qui montre mieux sa similarit avec pipe :

js
const asyncPipe =
  (...functions) =>
  (initialValue) =>
    functions.reduce(async (acc, fn) => fn(await acc), initialValue);

Utiliser reduce() avec des tableaux creux

reduce() ignore les lments manquants dans les tableaux creux, mais n'ignore pas les valeurs undefined.

js
console.log([1, 2, , 4].reduce((a, b) => a + b)); // 7
console.log([1, 2, undefined, 4].reduce((a, b) => a + b)); // NaN

Appeler reduce() sur des objets ressemblant des tableaux

La mthode reduce() lit la proprit length de this puis accde chaque proprit dont la cl est un entier non ngatif infrieur length.

js
const objetSimilaireTableau = {
  length: 3,
  0: 2,
  1: 3,
  2: 4,
  3: 99, // ignor par reduce() car length vaut 3
};
console.log(
  Array.prototype.reduce.call(objetSimilaireTableau, (x, y) => x + y),
);
// 9

Quand ne pas utiliser reduce()

Les fonctions d'ordre suprieur polyvalentes comme reduce() peuvent tre puissantes mais parfois difficiles comprendre, surtout pour les dveloppeureuses JavaScript moins exprimentes. Si le code est plus clair avec d'autres mthodes de tableau, il faut peser la lisibilit face aux autres avantages de reduce().

Notez que reduce() est toujours quivalent une boucle for...of, sauf qu'au lieu de modifier une variable dans la porte suprieure, on retourne la nouvelle valeur chaque itration :

js
const val = array.reduce((acc, cur) => update(acc, cur), initialValue);

// quivalent  :
let val = initialValue;
for (const cur of array) {
  val = update(val, cur);
}

Comme indiqu prcdemment, la raison pour laquelle on peut vouloir utiliser reduce() est d'imiter les pratiques de programmation fonctionnelle avec des donnes immuables. Ainsi, les dveloppeureuses qui respectent l'immuabilit de l'accumulateur copient souvent tout l'accumulateur chaque itration, comme ceci :

js
const names = ["Alice", "Bob", "Tiff", "Bruce", "Alice"];
const countedNames = names.reduce((allNames, name) => {
  const currCount = Object.hasOwn(allNames, name) ? allNames[name] : 0;
  return {
    ...allNames,
    [name]: currCount + 1,
  };
}, {});

Ce code est inefficace, car chaque itration doit copier tout l'objet allNames, qui peut tre volumineux selon le nombre de noms uniques. Ce code a une complexit dans le pire des cas en O(N^2), o N est la longueur de names.

Une meilleure alternative consiste muter l'objet allNames chaque itration. Cependant, si allNames est de toute faon modifi, il peut tre prfrable de convertir le reduce() en boucle for, ce qui est bien plus lisible :

js
const names = ["Alice", "Bob", "Tiff", "Bruce", "Alice"];
const countedNames = names.reduce((allNames, name) => {
  const currCount = allNames[name] ?? 0;
  allNames[name] = currCount + 1;
  // retourner allNames, sinon l'itration suivante reoit undefined
  return allNames;
}, Object.create(null));
js
const names = ["Alice", "Bob", "Tiff", "Bruce", "Alice"];
const countedNames = Object.create(null);
for (const name of names) {
  const currCount = countedNames[name] ?? 0;
  countedNames[name] = currCount + 1;
}

Ainsi, si votre accumulateur est un tableau ou un objet et que vous le copiez chaque itration, vous pouvez accidentellement introduire une complexit quadratique dans votre code, ce qui dgradera rapidement les performances sur de grandes donnes. Cela s'est produit dans du code rel : voir par exemple Rendre Tanstack Table 1000x plus rapide avec un changement d'une ligne (angl.).

Quelques cas d'usage acceptables de reduce() sont donns ci-dessus (notamment la somme d'un tableau, le chanage de promesses et le chanage de fonctions). Il existe d'autres cas o de meilleures alternatives reduce() existent.

  • Aplatir un tableau de tableaux. Utilisez plutt flat().

    js
    const flattened = array.reduce((acc, cur) => acc.concat(cur), []);
    
    js
    const flattened = array.flat();
    
  • Regrouper des objets selon une proprit. Utilisez plutt Object.groupBy().

    js
    const groups = array.reduce((acc, obj) => {
      const key = obj.name;
      const curGroup = acc[key] ?? [];
      return { ...acc, [key]: [...curGroup, obj] };
    }, {});
    
    js
    const groups = Object.groupBy(array, (obj) => obj.name);
    
  • Concatner des tableaux contenus dans un tableau d'objets. Utilisez plutt flatMap().

    js
    const friends = [
      { name: "Anna", books: ["Bible", "Harry Potter"] },
      { name: "Bob", books: ["Guerre et Paix", "Romo et Juliette"] },
      { name: "Alice", books: ["Le Seigneur des anneaux", "Shining"] },
    ];
    const allBooks = friends.reduce((acc, cur) => [...acc, ...cur.books], []);
    
    js
    const allBooks = friends.flatMap((person) => person.books);
    
  • Retirer les doublons d'un tableau. Utilisez plutt Set et Array.from().

    js
    const uniqArray = array.reduce(
      (acc, cur) => (acc.includes(cur) ? acc : [...acc, cur]),
      [],
    );
    
    js
    const uniqArray = Array.from(new Set(array));
    
  • liminer ou ajouter des lments dans un tableau. Utilisez plutt flatMap().

    js
    // Prend un tableau de nombres et spare les carrs parfaits en leurs racines carres
    const roots = array.reduce((acc, cur) => {
      if (cur < 0) return acc;
      const root = Math.sqrt(cur);
      if (Number.isInteger(root)) return [...acc, root, root];
      return [...acc, cur];
    }, []);
    
    js
    const roots = array.flatMap((val) => {
      if (val < 0) return [];
      const root = Math.sqrt(val);
      if (Number.isInteger(root)) return [root, root];
      return [val];
    });
    

    Si vous ne faites qu'liminer des lments d'un tableau, vous pouvez aussi utiliser filter().

  • Rechercher des lments ou tester si des lments satisfont une condition. Utilisez plutt find() et findIndex() ou some() et every(). Ces mthodes ont l'avantage supplmentaire de retourner le rsultat ds qu'il est certain, sans parcourir tout le tableau.

    js
    const allEven = array.reduce((acc, cur) => acc && cur % 2 === 0, true);
    
    js
    const allEven = array.every((val) => val % 2 === 0);
    

Dans les cas o reduce() est le meilleur choix, une bonne documentation et des noms de variables smantiques peuvent aider attnuer les problmes de lisibilit.

Spcifications

Spcification
ECMAScript 2027 LanguageSpecification
# sec-array.prototype.reduce

Compatibilit des navigateurs

Voir aussi


Web Proxy Viewer  |  New URL  |  Original Page