Questa traduzione è incompleta. Collabora alla traduzione di questo articolo dall’originale in lingua inglese.
Il metodo reduce() applica una funzione su un array di valori ( da sinistra verso destra ) che accumula iterativamente, attraverso una determinata operazione, ciascun elemento restituendo in output un unico valore(ridotto).
var sum = [0, 1, 2, 3].reduce(function(a, b) {
return a + b;
}, 0);
// la somma è 6
var list1 = [[0, 1], [2, 3], [4, 5]];
var list2 = [0, [1, [2, [3, [4, [5]]]]]];
const flatten = arr => arr.reduce((a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []);
flatten(list1); // returns [0, 1, 2, 3, 4, 5]
flatten(list2); // returns [0, 1, 2, 3, 4, 5]
Sintassi
arr.reduce(callback, [initialValue])
Parametri
callback- Funzione da eseguire su ciascun valore dell'array, prendendo 4 argomenti:
-
accumulator- Il valore accumulato precedentemente ritornato nella ultima invocazione del callback, o il valore iniziale, se fornito.(Vedi sotto).
currentValue- Il valore corrente dell'array , processato.
currentIndex- L' indice dell'elemento corrente dell'array, processato. Inizia con indice 0, se viene fornito un
initialValuei, con indice 1 altrimenti. array- L'array sul quale effettuare
reduce.
initialValue- Opzionale. Il valore da usare come primo argomento della prima chiamata del
callback.
Valore Restituito
Il valore risultante dalla riduzione.
Descrizione
reduce esegue una funzione callback (ricorsiva) una volta per ogni elemento presente nell'array, escludendo i buchi nell'array. Riceve in pasto quattro argomenti:
accumulatorcurrentValuecurrentIndexarray
La prima vollta che viene incovato il valore ricorsivo (callback) , accumulator e currentValue può essre uno dei due valori. Se viene fornito initialValue nella chiamata da ridurre , allora accumulator sarà uguale all' initialValue e currentValue sarà uguale al primo elemento dell'array. Se non viene fornito alcun initialValue , allora accumulator sarà uguale al primo valore nell'array e currentValue sarà uguale al secondo.
Nota: Se initialValue non viene fornito, reduce eseguirà la funzione ricorsiva iniziando dall'indive 1, saltando il valore 0. Se initialValue viene fornito, inizierà con l'indice a 0.
Se l'array è vuoto e non viene fornito alcun initialValue , verrà lanciata l'eccezione TypeError. Se l'array ha solamente un elemento (indipendentemente dalla posizione) e non è fornito alcun initialValue , o initialValue è fornito ma l'array è vuoto , il solo valore verrà restituito senza invocare la ricorsione (callback).
E' raccomandabile fornire sempre un valore iniziale perchè ci sono tre possibili output senza initialValue,come mostrato nel seguente esempio.
var maxCallback = ( pre, cur ) => Math.max( pre.x, cur.x );
var maxCallback2 = ( max, cur ) => Math.max( max, cur );
// reduce() senza valore iniziale
[ { x: 22 }, { x: 42 } ].reduce( maxCallback ); // 42
[ { x: 22 } ].reduce( maxCallback ); // { x: 22 }
[ ].reduce( maxCallback ); // TypeError
// map/reduce; la soluzione migliore che funziona anche per array vuoti
[ { x: 22 }, { x: 42 } ].map( el => el.x )
.reduce( maxCallback2, -Infinity );
Come funziona reduce
Supponiamo si incorra nel seguente uso di reduce:
[0, 1, 2, 3, 4].reduce(function(accumulator, currentValue, currentIndex, array) { returnaccumulator+ currentValue; });
La ricorsione (callback) verrà chiamata quattro volte, con argomenti e valori di ritorno a ciascuna chiamata come segue:
callback |
accumulator |
currentValue |
currentIndex |
array |
return value |
|---|---|---|---|---|---|
|
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 della callback (10).
Puoi anche fornire una Arrow Function al posto di una funzione completa. Il codice seguente fornisce lo stesso risultato del codice visto sopra:
[0, 1, 2, 3, 4].reduce( (prev, curr) => prev + curr );
Se avessi fornito un valore iniziale come secondo argomento a cui applicare reduce, il risultato sarebbe stato il seguente:
[0,1,2,3,4].reduce( (accumulator, currentValue, currentIndex, array) => { returnaccumulator+ currentValue; }, 10);
callback |
accumulator |
currentValue |
currentIndex |
array |
return value |
|---|---|---|---|---|---|
|
prima chiamta |
10 |
0 |
0 |
[0, 1, 2, 3, 4] |
10 |
|
seconda chiamta |
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 |
L'ultima chiamata ritorna il valore (20) che vienre restituito come risultato della funzione reduce.
Esempi
Somma di tutti i valori di un array
var sum = [0, 1, 2, 3].reduce(function(a, b) {
return a + b;
}, 0);
// sum is 6
Alternativametne scritta con le arrow function:
var total = [ 0, 1, 2, 3 ].reduce( ( acc, cur ) => acc + cur, 0 );
Appiattimento di array di array
var flattened = [[0, 1], [2, 3], [4, 5]].reduce(function(a, b) {
return a.concat(b);
}, []);
// flattened is [0, 1, 2, 3, 4, 5]
Altrimenti, scritta con arrow function:
var flattened = [[0, 1], [2, 3], [4, 5]].reduce( ( acc, cur ) => acc.concat(cur), [] );
Conteggio delle istanze di un valore 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 }
Limitare arrays in array di oggetti attraverso spread operator e initial vlaues
// friends - un array di oggetti
// dove il campo "books" dell'oggetto - lista dei libri preferiti
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 - lista che conterrà tutti i libri degli amici +
// lista addizionale contentua in initialValue
var allbooks = friends.reduce(function(prev, curr) {
return [...prev, ...curr.books];
}, ["Alphabet"]);
// allbooks = ["Alphabet", "Bible", "Harry Potter", "War and peace",
// "Romeo and Juliet", "The Lord of the Rings", "The Shining"]
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 usare motori JavaScript obsoleti che non supportano Object.defineProperty, è meglio non usare il metodo polyfill Array.prototype , perchè non puoi rendere l'array non-numerabile
Specificazioni
| Specification | Status | Comment |
|---|---|---|
| ECMAScript 5.1 (ECMA-262) The definition of 'Array.prototype.reduce' in that specification. |
Standard | Definizione iniziale. Implementata in JavaScript 1.8. |
| ECMAScript 2015 (6th Edition, ECMA-262) The definition of 'Array.prototype.reduce' in that specification. |
Standard | |
| ECMAScript 2017 Draft (ECMA-262) The definition of 'Array.prototype.reduce' in that specification. |
Draft |
Compatibilità browser
| Feature | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari |
|---|---|---|---|---|---|
| Basic support | (Yes) | 3.0 (1.9) | 9 | 10.5 | 4.0 |
| Feature | Android | Chrome for Android | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile |
|---|---|---|---|---|---|---|
| Basic support | (Yes) | (Yes) | (Yes) | (Yes) | (Yes) | (Yes) |