2015-09-18 17 views
13

Sto provando a filtrare tutti gli elementi in una matrice che sono più grandi di 10 in una nuova matrice. Non sto intenzionalmente utilizzando Array.prototype.filter() poiché voglio imparare il metodo reduce(). Ecco il codice giocavo conPerché Array.prototype.reduce() non sta prendendo una matrice vuota come accumulatore?

var collection = [3, 5, 11, 23, 1]; 
 

 
// fileter all the elements bigger than 10 to a new array 
 

 
var output = collection.reduce(function(filteredArr, collectionElemet) { 
 
    if (collectionElemet > 10) { 
 
    return filteredArr.push(collectionElemet); 
 
    } 
 
}, []);

mi aspettavo che sarebbe filteredArr essere inizializzato con un array vuoto al momento della prima esecuzione callback come accade con molti esempi forniti here. Ma quando eseguo questo codice, ottengo l'errore Cannot read property 'push' of undefined, dove sto scherzando? Grazie!

+0

Se la condizione è vera - si restituisce un numero, se non è vero - si restituisce un 'indefinito'. Se vuoi semplicemente filtrare - usa 'Array.prototype.filter', il tuo codice attuale così com'è è brutto e fuorviante. – zerkms

+0

@zerkms: Questo è giusto per il codice di produzione, non per l'istruzione/sperimentazione. L'OP afferma chiaramente di conoscere 'filter', ma sta cercando di capire' reduce'. – Amadan

+1

@Amadan, allora è un tentativo debole: ha senso provare a capire le funzioni usando gli scenari per cui sono stati progettati. – zerkms

risposta

26

è necessario restituire il filteredArr dalla funzione anonima, in modo che esso viene utilizzato come previousValue per la successiva chiamata

var collection = [3, 5, 11, 23, 1]; 

// filter all the elements bigger than 10 to a new array 

var output = collection.reduce(function(filteredArr, collectionElement) { 
    if (collectionElement > 10) { 
    filteredArr.push(collectionElement); 
    } 
    return filteredArr; 
}, []); 
4

Array.prototype.push restituirà la lunghezza del nuovo array. Devi restituire l'accumulatore. Un modo sintetico per farlo è con Array.prototype.concat, dal momento che il metodo effettivamente restituire la matrice:

var collection = [3, 5, 11, 23, 1]; 

var output = collection.reduce(function(filteredArr, collectionElemet) { 
    if (collectionElemet > 10) { 
    return filteredArr.concat(collectionElemet); 
    } 
}, []); 

È necessario restituire l'accumulatore così la prossima iterazione può utilizzare il valore dell'accumulatore.

+0

Non è il mio downvote, ma * concat * restituisce una nuova matrice ogni volta, il che è inefficiente. * push * è la scelta più ovvia per aggiungere nuovi elementi a un array esistente. – RobG

+1

Non sempre si tratta di efficienza, è una risposta valida perché illustra due cose, come creare una soluzione in una riga e che @segmentationfaulter deve restituire filteredArr. La sua confusione probabilmente stava pensando che filteredArr.push restituirà filtratoArr. – titusfx

Problemi correlati