Ok, si tratta più di una domanda di informatica, che di una domanda basata su un linguaggio particolare, ma c'è una differenza tra un'operazione di mappa e un'operazione di foreach? O sono semplicemente nomi diversi per la stessa cosa?
Ok, si tratta più di una domanda di informatica, che di una domanda basata su un linguaggio particolare, ma c'è una differenza tra un'operazione di mappa e un'operazione di foreach? O sono semplicemente nomi diversi per la stessa cosa?
Risposte:
Diverso.
foreach scorre su un elenco e applica alcune operazioni con effetti collaterali a ciascun membro dell'elenco (come ad esempio il salvataggio di ognuno nel database)
la mappa scorre su un elenco, trasforma ogni membro di quell'elenco e restituisce un altro elenco della stessa dimensione con i membri trasformati (come convertire un elenco di stringhe in maiuscolo)
map
non non comporta l'esecuzione della sua logica sottostante fino quando la lista trasformata atteso viene chiamato. Al contrario, foreach
l'operazione viene calcolata immediatamente.
La differenza importante tra loro è che map
accumula tutti i risultati in una raccolta, mentre foreach
non restituisce nulla. map
viene solitamente utilizzato quando si desidera trasformare una raccolta di elementi con una funzione, mentre foreach
esegue semplicemente un'azione per ciascun elemento.
In breve, foreach
è per applicare un'operazione su ciascun elemento di una raccolta di elementi, mentremap
per trasformare una raccolta in un'altra.
Esistono due differenze significative tra foreach
e map
.
foreach
non ha restrizioni concettuali sull'operazione che applica, a parte forse accettare un elemento come argomento. Cioè, l'operazione potrebbe non fare nulla, potrebbe avere un effetto collaterale, può restituire un valore o non può restituire un valore. Tuttiforeach
importa è iterare su una raccolta di elementi e applicare l'operazione su ciascun elemento.
map
d'altra parte, ha una restrizione sull'operazione: si aspetta che l'operazione restituisca un elemento e probabilmente accetta anche un elemento come argomento. L' map
operazione scorre su una raccolta di elementi, applicando l'operazione su ciascun elemento e infine memorizzando il risultato di ogni invocazione dell'operazione in un'altra raccolta. In altre parole, map
trasforma una raccolta in un'altra.
foreach
funziona con una singola raccolta di elementi. Questa è la raccolta di input.
map
funziona con due raccolte di elementi: la raccolta di input e la raccolta di output.
Non è un errore correlare i due algoritmi: in effetti, è possibile visualizzarli gerarchicamente, dove map
è una specializzazione di foreach
. Cioè, è possibile utilizzare foreach
e fare in modo che l'operazione trasformi il suo argomento e lo inserisca in un'altra raccolta. Quindi, l' foreach
algoritmo è un'astrazione, una generalizzazione, map
dell'algoritmo. In effetti, poiché foreach
non ha restrizioni sul suo funzionamento, possiamo tranquillamente affermare che foreach
è il meccanismo di looping più semplice in circolazione e che può fare qualsiasi cosa un loop possa fare. map
, così come altri algoritmi più specializzati, esiste per l'espressività: se desideri mappare (o trasformare) una raccolta in un'altra, la tua intenzione è più chiara se la usi map
che se la usi foreach
.
Possiamo estendere ulteriormente questa discussione e considerare l' copy
algoritmo: un ciclo che clona una raccolta. Anche questo algoritmo è una specializzazione foreach
dell'algoritmo. È possibile definire un'operazione che, dato un elemento, inserirà lo stesso elemento in un'altra raccolta. Se si utilizza foreach
con tale operazione, è stato effettivamente eseguito l' copy
algoritmo, sebbene con chiarezza, espressività o esplicitazione ridotte. Andiamo ancora oltre: possiamo dire che map
è una specializzazione di per copy
sé una specializzazione di foreach
. map
può cambiare uno qualsiasi degli elementi su cui scorre. Se map
non cambia nessuno degli elementi, semplicemente copia gli elementi e li usa copia esprimerebbe l'intento più chiaramente.
L' foreach
algoritmo stesso può avere o meno un valore di ritorno, a seconda della lingua. In C ++, ad esempio, foreach
restituisce l'operazione originariamente ricevuta. L'idea è che l'operazione potrebbe avere uno stato e potresti voler ricambiare l'operazione per controllare come si è evoluta sugli elementi. map
anche, può o non può restituire un valore. In C ++ transform
(l'equivalente per map
qui) capita di restituire un iteratore alla fine del contenitore di output (raccolta). In Ruby, il valore restituito di map
è la sequenza di output (raccolta). Quindi, il valore di ritorno degli algoritmi è davvero un dettaglio di implementazione; il loro effetto può o meno essere quello che restituiscono.
.forEach()
può essere utilizzato per implementare .map()
, vedere qui: stackoverflow.com/a/39159854/1524693
Array.protototype.map
metodo e Array.protototype.forEach
sono entrambi abbastanza simili.Esegui il seguente codice: http://labs.codecademy.com/bw1/6#:workspace
var arr = [1, 2, 3, 4, 5];
arr.map(function(val, ind, arr){
console.log("arr[" + ind + "]: " + Math.pow(val,2));
});
console.log();
arr.forEach(function(val, ind, arr){
console.log("arr[" + ind + "]: " + Math.pow(val,2));
});
Danno il risultato esatto idem.
arr[0]: 1
arr[1]: 4
arr[2]: 9
arr[3]: 16
arr[4]: 25
arr[0]: 1
arr[1]: 4
arr[2]: 9
arr[3]: 16
arr[4]: 25
Qui ho semplicemente assegnato il risultato del valore restituito dalla mappa e per ogni metodo.
var arr = [1, 2, 3, 4, 5];
var ar1 = arr.map(function(val, ind, arr){
console.log("arr[" + ind + "]: " + Math.pow(val,2));
return val;
});
console.log();
console.log(ar1);
console.log();
var ar2 = arr.forEach(function(val, ind, arr){
console.log("arr[" + ind + "]: " + Math.pow(val,2));
return val;
});
console.log();
console.log(ar2);
console.log();
Ora il risultato è qualcosa di complicato!
arr[0]: 1
arr[1]: 4
arr[2]: 9
arr[3]: 16
arr[4]: 25
[ 1, 2, 3, 4, 5 ]
arr[0]: 1
arr[1]: 4
arr[2]: 9
arr[3]: 16
arr[4]: 25
undefined
Array.prototype.map
restituisce un array ma Array.prototype.forEach
non lo fa. Quindi è possibile manipolare l'array restituito all'interno della funzione di callback passata al metodo map e quindi restituirlo.
Array.prototype.forEach
cammina solo attraverso l'array dato in modo che tu possa fare le tue cose mentre cammini nell'array.
la differenza più 'visibile' è che la mappa accumula il risultato in una nuova raccolta, mentre foreach viene fatto solo per l'esecuzione stessa.
ma ci sono un paio di ipotesi extra: poiché lo "scopo" della mappa è il nuovo elenco di valori, non importa davvero l'ordine di esecuzione. in effetti, alcuni ambienti di esecuzione generano codice parallelo, o addirittura introducono alcuni memoizing per evitare di chiamare valori ripetuti, o pigrizia, per evitare di chiamarli affatto.
foreach, d'altra parte, è chiamato specificamente per gli effetti collaterali; pertanto l'ordine è importante e di solito non può essere parallelizzato.
Risposta breve: map
e forEach
sono diversi. Inoltre, informalmente parlando, map
è un superset rigoroso di forEach
.
Risposta lunga: in primo luogo, arriviamo a una riga di descrizioni di forEach
e map
:
forEach
scorre su tutti gli elementi, chiamando la funzione fornita su ciascuno di essi.map
scorre su tutti gli elementi, chiamando la funzione fornita su ciascuno e produce un array trasformato ricordando il risultato di ciascuna chiamata di funzione.In molte lingue, forEach
viene spesso chiamato solo each
. La seguente discussione utilizza JavaScript solo come riferimento. Potrebbe davvero essere qualsiasi altra lingua.
Ora, usiamo ognuna di queste funzioni.
forEach
:Attività 1: scrivere una funzione printSquares
, che accetta una matrice di numeriarr
e stampa il quadrato di ciascun elemento in essa.
Soluzione 1:
var printSquares = function (arr) {
arr.forEach(function (n) {
console.log(n * n);
});
};
map
:Attività 2: scrivere una funzione selfDot
, che accetta una matrice di numeri arr
e restituisce una matrice in cui ogni elemento è il quadrato dell'elemento corrispondente inarr
.
A parte: qui, in termini gergali, stiamo cercando di quadrare l'array di input. In termini formali, stiamo cercando di calcolare il suo prodotto punto con se stesso.
Soluzione 2:
var selfDot = function (arr) {
return arr.map(function (n) {
return n * n;
});
};
map
un superset diforEach
?È possibile utilizzare map
per risolvere entrambe le attività, Attività 1 e Attività 2 . Tuttavia, non è possibile utilizzare forEach
per risolvere l' attività 2 .
Nella soluzione 1 , se si sostituisce semplicemente forEach
con map
, la soluzione sarà comunque valida. Nella soluzione 2 , tuttavia, la sostituzione map
con forEach
interromperà la soluzione precedentemente funzionante.
forEach
in termini di map
:Un altro modo di realizzare map
la superiorità è implementare forEach
in termini di map
. Dato che siamo dei bravi programmatori, non ci abbandoneremo all'inquinamento dello spazio dei nomi. Chiameremo il nostro forEach
, giusto each
.
Array.prototype.each = function (func) {
this.map(func);
};
Ora, se non ti piace l' prototype
assurdità, ecco qui:
var each = function (arr, func) {
arr.map(func); // Or map(arr, func);
};
forEach
esiste?La risposta è efficienza. Se non sei interessato a trasformare un array in un altro array, perché dovresti calcolare l'array trasformato? Solo per scaricarlo? Ovviamente no! Se non vuoi una trasformazione, non dovresti fare una trasformazione.
Quindi, mentre la mappa può essere utilizzata per risolvere l' attività 1 , probabilmente non dovrebbe. Per ognuno è il candidato giusto per quello.
Mentre sono in gran parte d'accordo con la risposta di @madlep, vorrei sottolineare che si map()
tratta di un super set rigoroso di forEach()
.
Sì, map()
viene solitamente utilizzato per creare un nuovo array. Tuttavia, può anche essere utilizzato per modificare l'array corrente.
Ecco un esempio:
var a = [0, 1, 2, 3, 4], b = null;
b = a.map(function (x) { a[x] = 'What!!'; return x*x; });
console.log(b); // logs [0, 1, 4, 9, 16]
console.log(a); // logs ["What!!", "What!!", "What!!", "What!!", "What!!"]
Nell'esempio sopra, è a
stato convenientemente impostato tale che a[i] === i
per i < a.length
. Anche così, dimostra il potere dimap()
.
Ecco la descrizione ufficiale dimap()
. Nota che map()
potrebbe persino cambiare l'array su cui viene chiamato! Grandine map()
.
Spero che questo abbia aiutato.
A cura del 10-nov-2015: aggiunta elaborazione.
map
funzione nativa ma no forEach
; non potresti semplicemente non usare map
invece di forEach
? D'altro canto, se una lingua avesse forEach
ma no map
, dovresti implementare la tua map
. Non puoi semplicemente usare forEach
invece di map
. Ditemi cosa ne pensate.
Ecco un esempio in Scala usando gli elenchi: map restituisce l'elenco, foreach non restituisce nulla.
def map(f: Int ⇒ Int): List[Int]
def foreach(f: Int ⇒ Unit): Unit
Quindi map restituisce l'elenco risultante dall'applicazione della funzione f a ciascun elemento dell'elenco:
scala> val list = List(1, 2, 3)
list: List[Int] = List(1, 2, 3)
scala> list map (x => x * 2)
res0: List[Int] = List(2, 4, 6)
Foreach applica solo f a ciascun elemento:
scala> var sum = 0
sum: Int = 0
scala> list foreach (sum += _)
scala> sum
res2: Int = 6 // res1 is empty
Se stai parlando di Javascript in particolare, la differenza è che map
è una funzione loop mentreforEach
è un iteratore.
Uso map
quando si desidera applicare un'operazione a ciascun membro dell'elenco e ottenere i risultati come nuovo elenco, senza influire sull'elenco originale.
Usa forEach
quando vuoi fare qualcosa sulla base di ciascun elemento dell'elenco. Ad esempio, potresti aggiungere elementi alla pagina. Fondamentalmente, è ottimo per quando vuoi "effetti collaterali".
Altre differenze: forEach
non restituisce nulla (poiché è in realtà una funzione del flusso di controllo) e la funzione pass-in ottiene riferimenti all'indice e all'intero elenco, mentre map restituisce il nuovo elenco e passa solo l'elemento corrente.
Ciascuno cerca di applicare una funzione come scrivere su db ecc su ogni elemento del RDD senza restituire nulla.
Ma map()
applica una funzione sugli elementi di rdd e restituisce il rdd. Quindi quando esegui il metodo seguente non fallirà alla riga 3 ma mentre raccogli il rdd dopo aver applicato foreach fallirà e genererà un errore che dice
File "<stdin>", riga 5, in <modulo>
AttributeError: l'oggetto 'NoneType' non ha alcun attributo 'collect'
nums = sc.parallelize([1,2,3,4,5,6,7,8,9,10])
num2 = nums.map(lambda x: x+2)
print ("num2",num2.collect())
num3 = nums.foreach(lambda x : x*x)
print ("num3",num3.collect())
Iterator[String]
dascala.io.Source.fromFile("/home/me/file").getLines()
e lo applico.foreach(s => ptintln(s))
, viene stampato ok ma si svuota subito dopo. Allo stesso tempo, se lo applico.map(ptintln(_))
, si svuota e non viene stampato nulla.