Questo contenuto viene visualizzato in inglese perché non è ancora disponibile una versione tradotta nella lingua selezionata. Aiutaci a tradurre questo articolo!
Il metodo reduce()
esegue una funzione reducer (che tu fornisci) su ogni elemento dell'array, risultante in un unico output.
The source for this interactive example is stored in a GitHub repository. If you'd like to contribute to the interactive examples project, please clone https://github.com/mdn/interactive-examples and send us a pull request.
La funzione reducer accetta quattro argomenti:
- Accumulatore (acc)
- Valore corrente (cur)
- Indice corrente (idx)
- Array sul quale viene eseguito il metodo (src)
Il valore restituito della funzione reducer viene assegnato all'accumulatore, il cui valore viene memorizzato attraverso ogni iterazione nell'intero array e in definitiva, diventa il valore finale finale singolo.
Sintassi
arr.reduce(callback(accumulator, currentValue[, index[, array]]), [, initialValue])
Parametri
callback
- Una funzione da eseguire su ogni elemento dell'array (tranne il primo, se non viene fornita
initialValue
), accetta 4 argomenti:accumulator
- L'accumulatore accumula i valori di ritorno del callback. È il valore accumulato precedentemente restituito nell'ultima chiamata del callback o
initialValue
, se fornito (vedere di seguito). currentValue
- L'elemento corrente in elaborazione nell'array.
index
Optional- L'indice dell'elemento corrente in elaborazione nell'array. Inizia dall'indice 0 se viene fornito
initialValue
Altrimenti, inizia dall'indice 1. array
Optional- L'array a cui viene applicato
reduce()
.
initialValue
Optional- Un valore da utilizzare come primo argomento della prima chiamata del
callback
. Se non viene fornitoinitialValue
il primo elemento dell'array verrà utilizzato e saltato. Chiamarereduce()
su un array vuoto senzainitialValue
genererà unTypeError
.
Valore di ritorno
Il singolo valore che risulta dalla riduzione.
Descrizione
Il metodo reduce()
esegue il callback
una volta per ogni valore assegnato presente nell'array, prendendo quattro argomenti:
accumulator
currentValue
currentIndex
array
La prima volta che viene chiamato il callback, accumulator
e currentValue
possono essere uno dei due valori. Se initialValue
viene fornito nella chiamata a reduce()
, accumulator
sarà uguale a initialValue
, e currentValue
sarà uguale al primo valore nell'array. Se non viene fornito alcun valore initialValue
, accumulator
sarà uguale al primo valore dell'array e currentValue
sarà uguale al secondo.
Note: Se non viene fornito initialValue
, reduce()
eseguirà la funzione di callback a partire dall'indice 1, saltando il primo indice. Se viene fornito initialValue
, inizierà dall'indice 0.
Se l'array è vuoto e non viene fornito initialValue
verrà generato un TypeError
. Se l'array ha solo un elemento (indipendentemente dalla posizione) e non viene fornito initialValue
, o se è fornito initialValue
ma l'array è vuoto, il valore solo verrà restituito senza chiamare callback
.
Di solito è più sicuro fornire initialValue
perché ci sono tre output possibili senza initialValue
, come mostrato nell'esempio seguente.
var maxCallback = ( acc, cur ) => Math.max( acc.x, cur.x ); var maxCallback2 = ( max, cur ) => Math.max( max, cur ); // reduce() without initialValue [ { x: 22 }, { x: 42 } ].reduce( maxCallback ); // 42 [ { x: 22 } ].reduce( maxCallback ); // { x: 22 } [ ].reduce( maxCallback ); // TypeError // map/reduce; better solution, also works for empty or larger arrays [ { x: 22 }, { x: 42 } ].map( el => el.x ) .reduce( maxCallback2, -Infinity );
Come funziona reduce()
Supponiamo che si sia verificato il seguente uso di reduce()
:
[0, 1, 2, 3, 4].reduce(function(accumulator, currentValue, currentIndex, array) { return accumulator + currentValue; });
Il callback verrebbe invocato quattro volte, con gli argomenti e i valori restituiti in ogni chiamata come segue:
callback |
accumulator |
currentValue |
currentIndex |
array |
valore ritornato |
---|---|---|---|---|---|
prima chiamata | 0 |
1 |
1 | [0, 1, 2, 3, 4] |
1 |
seconda chiamata | 1 |
2 |
2 | [0, 1, 2, 3, 4] |
3 |
terza chiamata | 3 |
3 |
3 | [0, 1, 2, 3, 4] |
6 |
quarta chiamata | 6 |
4 |
4 | [0, 1, 2, 3, 4] |
10 |
Il valore restituito da reduce()
sarà quello dell'ultima chiamata del callback (10
).
È inoltre possibile fornire una Arrow Function al posto di una funzione completa. Il seguente codice produrrà lo stesso output del codice nel blocco sopra riportato:
[0, 1, 2, 3, 4].reduce( (accumulator, currentValue, currentIndex, array) => accumulator + currentValue );
Se dovessi fornire initialValue
come secondo argomento a reduce()
, il risultato sarebbe simile a questo:
[0, 1, 2, 3, 4].reduce((accumulator, currentValue, currentIndex, array) => { return accumulator + currentValue; }, 10);
callback |
accumulator |
currentValue |
currentIndex |
array |
valore restituito |
---|---|---|---|---|---|
prima chiamata | 10 |
0 |
0 |
[0, 1, 2, 3, 4] |
10 |
seconda chiamata | 10 |
1 |
1 |
[0, 1, 2, 3, 4] |
11 |
terza chiamata | 11 |
2 |
2 |
[0, 1, 2, 3, 4] |
13 |
quarta chiamata | 13 |
3 |
3 |
[0, 1, 2, 3, 4] |
16 |
quinta chiamata | 16 |
4 |
4 |
[0, 1, 2, 3, 4] |
20 |
Il valore restituito da reduce()
in questo caso sarebbe 20
.
Esempi
Sommare tutti i valori di un array
var sum = [0, 1, 2, 3].reduce(function (accumulator, currentValue) { return accumulator + currentValue; }, 0); // sum è 6
In alternativa scritto con una arrow function:
var total = [ 0, 1, 2, 3 ].reduce( ( accumulator, currentValue ) => accumulator + currentValue, 0 );
Somma dei valori in un array di oggetti
Per riassumere i valori contenuti in un array di oggetti, devi fornire initialValue
, in modo che ogni elemento passi attraverso la tua funzione
var initialValue = 0; var sum = [{x: 1}, {x: 2}, {x: 3}].reduce(function (accumulator, currentValue) { return accumulator + currentValue.x; },initialValue) console.log(sum) // logs 6
In alternativa scritto con una arrow function:
var initialValue = 0; var sum = [{x: 1}, {x: 2}, {x: 3}].reduce( (accumulator, currentValue) => accumulator + currentValue.x ,initialValue ); console.log(sum) // logs 6
Appiattire una serie di array
var flattened = [[0, 1], [2, 3], [4, 5]].reduce( function(accumulator, currentValue) { return accumulator.concat(currentValue); }, [] ); // flattened is [0, 1, 2, 3, 4, 5]
In alternativa scritto con una arrow function:
var flattened = [[0, 1], [2, 3], [4, 5]].reduce( ( accumulator, currentValue ) => accumulator.concat(currentValue), [] );
Conteggio delle istanze di valori in un oggetto
var names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice']; var countedNames = names.reduce(function (allNames, name) { if (name in allNames) { allNames[name]++; } else { allNames[name] = 1; } return allNames; }, {}); // countedNames is: // { 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 }
Raggruppamento di oggetti in base a una proprietà
var people = [ { name: 'Alice', age: 21 }, { name: 'Max', age: 20 }, { name: 'Jane', age: 20 } ]; function groupBy(objectArray, property) { return objectArray.reduce(function (acc, obj) { var key = obj[property]; if (!acc[key]) { acc[key] = []; } acc[key].push(obj); return acc; }, {}); } var groupedPeople = groupBy(people, 'age'); // groupedPeople is: // { // 20: [ // { name: 'Max', age: 20 }, // { name: 'Jane', age: 20 } // ], // 21: [{ name: 'Alice', age: 21 }] // }
Array di legame contenuti in una serie di oggetti che utilizzano lo spread operator e initialValue
// friends - an array of objects // where object field "books" - list of favorite books var friends = [{ name: 'Anna', books: ['Bible', 'Harry Potter'], age: 21 }, { name: 'Bob', books: ['War and peace', 'Romeo and Juliet'], age: 26 }, { name: 'Alice', books: ['The Lord of the Rings', 'The Shining'], age: 18 }]; // allbooks - list which will contain all friends' books + // additional list contained in initialValue var allbooks = friends.reduce(function(accumulator, currentValue) { return [...accumulator, ...currentValue.books]; }, ['Alphabet']); // allbooks = [ // 'Alphabet', 'Bible', 'Harry Potter', 'War and peace', // 'Romeo and Juliet', 'The Lord of the Rings', // 'The Shining' // ]
Rimuovi gli elementi duplicati nell'array
Note: Se si utilizza un ambiente compatibile con Set
e Array.from()
, è possibile utilizzare let orderedArray = Array.from(new Set(myArray));
per ottenere un array in cui sono stati rimossi gli elementi duplicati.
var myArray = ['a', 'b', 'a', 'b', 'c', 'e', 'e', 'c', 'd', 'd', 'd', 'd']; var myOrderedArray = myArray.reduce(function (accumulator, currentValue) { if (accumulator.indexOf(currentValue) === -1) { accumulator.push(currentValue); } return accumulator }, []) console.log(myOrderedArray);
Eseguire le Promises in Sequenza
/** * Esegue promises da un array di funzioni che possono restituire promises * in modo concatenato * * @param {array} arr - promise arr * @return {Object} promise object */ function runPromiseInSequence(arr, input) { return arr.reduce( (promiseChain, currentFunction) => promiseChain.then(currentFunction), Promise.resolve(input) ); } // promise function 1 function p1(a) { return new Promise((resolve, reject) => { resolve(a * 5); }); } // promise function 2 function p2(a) { return new Promise((resolve, reject) => { resolve(a * 2); }); } // function 3 - sarà avvolta in una promise risolta da .then() function f3(a) { return a * 3; } // promise function 4 function p4(a) { return new Promise((resolve, reject) => { resolve(a * 4); }); } const promiseArr = [p1, p2, f3, p4]; runPromiseInSequence(promiseArr, 10) .then(console.log); // 1200
Composizione funzionale per tubazioni
// Elementi da utilizzare per la composizione const double = x => x + x; const triple = x => 3 * x; const quadruple = x => 4 * x; // Function composition enabling pipe functionality const pipe = (...functions) => input => functions.reduce( (acc, fn) => fn(acc), input ); // Funzioni composte per la moltiplicazione di valori specifici const multiply6 = pipe(double, triple); const multiply9 = pipe(triple, triple); const multiply16 = pipe(quadruple, quadruple); const multiply24 = pipe(double, triple, quadruple); // Utilizzo multiply6(6); // 36 multiply9(9); // 81 multiply16(16); // 256 multiply24(10); // 240
Scrivere map usando reduce
if (!Array.prototype.mapUsingReduce) { Array.prototype.mapUsingReduce = function(callback, thisArg) { return this.reduce(function(mappedArray, currentValue, index, array) { mappedArray[index] = callback.call(thisArg, currentValue, index, array); return mappedArray; }, []); }; } [1, 2, , 3].mapUsingReduce( (currentValue, index, array) => currentValue + index + array.length ); // [5, 7, , 10]
Polyfill
// Production steps of ECMA-262, Edition 5, 15.4.4.21 // Reference: http://es5.github.io/#x15.4.4.21 // https://tc39.github.io/ecma262/#sec-array.prototype.reduce if (!Array.prototype.reduce) { Object.defineProperty(Array.prototype, 'reduce', { value: function(callback /*, initialValue*/) { if (this === null) { throw new TypeError( 'Array.prototype.reduce ' + 'called on null or undefined' ); } if (typeof callback !== 'function') { throw new TypeError( callback + ' is not a function'); } // 1. Let O be ? ToObject(this value). var o = Object(this); // 2. Let len be ? ToLength(? Get(O, "length")). var len = o.length >>> 0; // Steps 3, 4, 5, 6, 7 var k = 0; var value; if (arguments.length >= 2) { value = arguments[1]; } else { while (k < len && !(k in o)) { k++; } // 3. If len is 0 and initialValue is not present, // throw a TypeError exception. if (k >= len) { throw new TypeError( 'Reduce of empty array ' + 'with no initial value' ); } value = o[k++]; } // 8. Repeat, while k < len while (k < len) { // a. Let Pk be ! ToString(k). // b. Let kPresent be ? HasProperty(O, Pk). // c. If kPresent is true, then // i. Let kValue be ? Get(O, Pk). // ii. Let accumulator be ? Call( // callbackfn, undefined, // « accumulator, kValue, k, O »). if (k in o) { value = callback(value, o[k], k, o); } // d. Increase k by 1. k++; } // 9. Return accumulator. return value; } }); }
Se hai bisogno di supportare motori JavaScript veramente obsoleti che non supportano Object.defineProperty()
, è meglio non applicare polyfills ai metodi di Array.prototype
, poiché non puoi renderli non enumerabili.
Specifiche
Specifica | Stato | Commento |
---|---|---|
ECMAScript 5.1 (ECMA-262) The definition of 'Array.prototype.reduce()' in that specification. |
Standard | Definizione iniziale Implementato in JavaScript 1.8. |
ECMAScript 2015 (6th Edition, ECMA-262) The definition of 'Array.prototype.reduce()' in that specification. |
Standard | |
ECMAScript Latest Draft (ECMA-262) The definition of 'Array.prototype.reduce()' in that specification. |
Draft |
Compatibilità con i browser
Desktop | Mobile | Server | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
reduce | Chrome Full support 3 | Edge Full support 12 | Firefox Full support 3 | IE Full support 9 | Opera Full support 10.5 | Safari Full support 4.1 | WebView Android Full support ≤37 | Chrome Android Full support 18 | Firefox Android Full support 4 | Opera Android Full support Yes | Safari iOS Full support 4 | Samsung Internet Android Full support 1.0 | nodejs Full support Yes |
Legend
- Full support
- Full support