--- title: Array.prototype.reduce() slug: Web/JavaScript/Reference/Global_Objects/Array/Reduce tags: - Array - ECMAScript 5 - JavaScript - Méthode - Prototype - Reference translation_of: Web/JavaScript/Reference/Global_Objects/Array/Reduce original_slug: Web/JavaScript/Reference/Objets_globaux/Array/reduce ---
La méthode reduce()
applique une fonction qui est un « accumulateur » et qui traite chaque valeur d'une liste (de la gauche vers la droite) afin de la réduire à une seule valeur.
Le code source de cet exemple interactif est disponible dans un dépôt GitHub. Si vous souhaitez contribuez à ces exemples, n'hésitez pas à cloner https://github.com/mdn/interactive-examples et à envoyer une pull request !
arr.reduce(callback) arr.reduce(callback, valeurInitiale)
callback
valeurInitiale
n'est fournie), elle prend quatre arguments en entrée :
accumulateur
valeurInitiale
, si elle est fournie (voir ci-après) (c'est la valeur « accumulée » au fur et à mesure des appelsvaleurCourante
index
{{optional_inline}}array
{{optional_inline}}reduce()
.valeurInitiale
{{optional_inline}}callback
. Si aucune valeur initiale n'est fournie, le premier élément du tableau est utilisé (et la boucle de traitement ne le parcourera pas). Si on appelle reduce()
sur un tableau vide sans fournir de valeur initiale, on aura une erreur.La valeur obtenue grâce à la fonction de réduction.
reduce()
exécute la fonction callback
une fois pour chaque élément présent dans le tableau et ignore les éléments vides du tableau. La fonction callback
utilise quatre arguments :
callback
), ou la valeur initiale s'il sagit du premier appel ;La première fois que la fonction callback
est appelée, valeurInitiale
et valeurCourante
peuvent correspondre à un ou deux éléments. Si valeurInitiale
est fournie dans l'appel de reduce()
, alors accumulateur
sera égale à valeurInitiale
et valeurCourante
sera égale à la première valeur de la liste. Si valeurInitiale
n'est pas fournie, alors accumulateur
sera égale à la première valeur de la liste, et valeurCourante
sera alors égale à la seconde.
Autrement dit, si valeurInitiale
n'est pas fournie, reduce
exécutera la fonction de rappel à partir de l'indice 1 et la première valeur du tableau (d'indice 0) sera utilisée pour valeurInitiale
.
En considérant le code suivant :
[0, 1, 2, 3, 4].reduce(function(accumulateur, valeurCourante, index, array){ return accumulateur + valeurCourante; });
La fonction callback
sera appelée quatre fois, avec les arguments et les valeurs de retour de chaque appel suivant :
accumulateur |
valeurCourante |
index |
array |
valeur retournée | |
---|---|---|---|---|---|
premier appel | 0 |
1 |
1 |
[0,1,2,3,4] |
1 |
deuxième appel | 1 |
2 |
2 |
[0,1,2,3,4] |
3 |
troisième appel | 3 |
3 |
3 |
[0,1,2,3,4] |
6 |
quatrième appel | 6 |
4 |
4 |
[0,1,2,3,4] |
10 |
La valeur retournée par reduce()
sera alors celle du dernier appel de la callback (ici 10
).
Il est aussi possible d'utiliser une {{jsxref("Fonctions/Fonctions_fléchées","fonction fléchée","",1)}} au lieu d'une fonction classique. Le code suivant, par exemple, produit le même résultat que l'exemple précédent :
[0, 1, 2, 3, 4].reduce( (accumulateur, valeurCourante) => accumulateur + valeurCourante; );
Si on fournit une valeur initiale comme second argument à l'appel de reduce()
, le résultat sera alors le suivant :
[0, 1, 2, 3, 4].reduce(function(accumulateur, valeurCourante, index, array){ return accumulateur + valeurCourante; }, 10);
accumulateur |
valeurCourante |
index |
array |
valeur retournée | |
---|---|---|---|---|---|
premier appel | 10 |
0 |
0 |
[0,1,2,3,4] |
10 |
deuxième appel | 10 |
1 |
1 |
[0,1,2,3,4] |
11 |
troisième appel | 11 |
2 |
2 |
[0,1,2,3,4] |
13 |
quatrième appel | 13 |
3 |
3 |
[0,1,2,3,4] |
16 |
cinquième appel | 16 |
4 |
4 |
[0,1,2,3,4] |
20 |
Ici, la valeur renvoyée par reduce()
serait 20
.
var total = [0, 1, 2, 3].reduce((a, b)=> a + b,0); // total == 6
Pour additionner les valeurs d'une propriété donnée des objets d'un tableau, il sera nécessaire de fournir une valeur initiale afin que tous les éléments soient parcourus :
var valeurInitiale = 0; var somme = [{x: 1}, {x:2}, {x:3}].reduce(function (accumulateur, valeurCourante) { return accumulateur + valeurCourante.x; }, valeurInitiale); console.log(somme); // affiche 6 dans la console
On peut également écrire une version plus concise avec les fonctions fléchées :
var valeurInitiale = 0; var somme = [{x: 1}, {x:2}, {x:3}].reduce( (accumulateur, valeurCourante) => accumulateur + valeurCourante.x , valeurInitiale ); console.log(somme); // affiche 6 dans la console
var applati = [[0, 1], [2, 3], [4, 5]].reduce(function(a, b) { return a.concat(b); }); // applati vaut [0, 1, 2, 3, 4, 5]
valeurInitiale
var amis = [ { "nom": "Quentin", "livres": ["City Hall", "Harry Potter"]}, { "nom": "Alice", "livres": ["L'Avare", "Les Fleurs du Mal"]} ] var tousLivres = amis.reduce(function(prev, curr) { return [...prev, ...curr.livres]; }, ["Perceval"]); // tousLivres = ["Perceval", "City Hall", "Harry Potter", // "L'Avare", "Les Fleurs du Mal"]
/** * Exécuter un enchaînement de promesses à partir d'un tableau * * @param {array} arr - un tableau de promesses * @return {Object} un objet Promise */ function runPromiseInSequense(arr) { return arr.reduce((promiseChain, currentPromise) => { return promiseChain.then((chainedResult) => { return currentPromise(chainedResult) .then((res) => res) }) }, Promise.resolve()); } // promise function 1 function p1() { return new Promise((resolve, reject) => { resolve(5); }); } // promise function 2 function p2(a) { return new Promise((resolve, reject) => { resolve(a * 2); }); } // promise function 3 function p3(a) { return new Promise((resolve, reject) => { resolve(a * 3); }); } const promiseArr = [p1, p2, p3]; runPromiseInSequense(promiseArr) .then((res) => { console.log(res); // 30 });
var personnes = [ { nom: "Alice", age: 21 }, { nom: "Bob", age: 20 }, { nom: "Charlie", age: 20 } ]; function groupBy(tableauObjets, propriete){ return tableauObjets.reduce(function (acc, obj) { var cle = obj[propriete]; if(!acc[cle]){ acc[cle] = []; } acc[cle].push(obj); return acc; }, {}); } var personnesParAge = groupBy(personnes, "age"); // personnesParAge aura la valeur : // { // 20: [ // { nom: "Bob", age: 20 }, // { nom: "Charlie", age: 20 } // ], // 21: [{ nom: "Alice", age: 21 }] // }
// Les briques de base que nous allons composer const double = x => x + x; const triple = x => 3 * x; const quadruple = x => 4 * x; // Une fonction qui permet d'appliquer une composition const pipe = (...functions) => input => functions.reduce( (acc, fn) => fn(acc), input ); // On crée des fonctions pour multiplier par un facteur donné 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
let tableauAvecDoublons = [1, 2, 3, 1, 4, 5, 4, 6]; let tableauSansDoublon = Array.from(new Set(tableauAvecDoublons)); console.table(tableauSansDoublon); // [1, 2, 3, 4, 5, 6]
reduce()
var tableauAvecDoublons = [1, 2, 3, 1, 4, 5, 4, 6]; var tableauSansDoublon = tableauAvecDoublon.reduce(function (acc, valCourante) { if(acc.indexOf(valCourante) === -1) { acc.push(valCourante); } return acc }, []); console.log(tableauSansDoublon); // [1, 2, 3, 4, 5, 6]
Spécification | État | Commentaires |
---|---|---|
{{SpecName('ES5.1', '#sec-15.4.4.21', 'Array.prototype.reduce()')}} | {{Spec2('ES5.1')}} | Définition initiale. Implémenté dans JavaScript 1.8 |
{{SpecName('ES6', '#sec-array.prototype.reduce', 'Array.prototype.reduce()')}} | {{Spec2('ES6')}} | |
{{SpecName('ESDraft', '#sec-array.prototype.reduce', 'Array.prototype.reduce()')}} | {{Spec2('ESDraft')}} |
{{Compat("javascript.builtins.Array.reduce")}}