Array # each vs Array # map


92
hash = { "d" => [11, 22], "f" => [33, 44, 55] }

# case 1
hash.map {|k,vs| vs.map {|v| "#{k}:#{v}"}}.join(",")
=> "d:11,d:22,f:33,f:44,f:55"

# case 2
hash.map {|k,vs| vs.each {|v| "#{k}:#{v}"}}.join(",")
=> "11,22,33,44,55"

l'unica differenza è il caso 1 utilizza vs.map, il caso 2 utilizza vs.each.

Cos'è successo qua?

Risposte:


174

Array#each esegue il blocco dato per ogni elemento dell'array, quindi restituisce l'array stesso.

Array#map esegue anche il blocco dato per ogni elemento dell'array, ma restituisce un nuovo array i cui valori sono i valori di ritorno di ogni iterazione del blocco.

Esempio: supponi di avere un array definito in questo modo:

arr = ["tokyo", "london", "rio"]

Quindi prova a eseguire each:

arr.each { |element| element.capitalize }
# => ["tokyo", "london", "rio"]

Nota che il valore restituito è semplicemente lo stesso array. Il codice all'interno del eachblocco viene eseguito, ma i valori calcolati non vengono restituiti; e poiché il codice non ha effetti collaterali, questo esempio non esegue alcun lavoro utile.

Al contrario, la chiamata al mapmetodo dell'array restituisce un nuovo array i cui elementi sono i valori di ritorno di ogni round di esecuzione del mapblocco:

arr.map { |element| element.capitalize }
# => ["Tokyo", "London", "Rio"]

Risposta perfetta per capire. Solo un .. Dichiarazione di non responsabilità: se si utilizza in modo eccessivo il valore di ritorno della funzione map, è possibile sprecare molta memoria.
Imran Ahmad,

33

Gli effetti collaterali sono gli stessi, il che aggiunge un po 'di confusione al tuo reverse engineering.

Sì, entrambi iterano sull'array (in realtà, su tutto ciò che si mescola in Enumerable ) ma map restituirà un Array composto dai risultati del blocco mentre ognuno restituirà semplicemente l'Array originale.

Il valore di ritorno di ciascuno è solo l'array originale ed è usato raramente nel codice Ruby, ma map è uno degli strumenti funzionali più importanti .

Ciò che mapfa è restituire un array che contiene i risultati del blocco o del metodo denominato passato. Per esempio:

    2.2.3 :001 > [:how, :now, :brown, :cow].map &:to_s
 => ["how", "now", "brown", "cow"]

In questo caso non ho passato un blocco ma solo un Symbol, tuttavia gli class Symbologgetti hanno un to_procmetodo che risulterà in:

[:how.to_s, :now.to_s, ...]

BTW, potresti avere difficoltà a trovare la documentazione perché map è un metodo in Enumerable mentre each (l'unico metodo richiesto dal modulo Enumerable ) è un metodo in Array .

Come nota curiosa: l' implementazione della mappa si basa su ciascuna di esse .


13

Ecco una rapida demo di come le mappe differiscono da ciascuna

a = ["a", "b", "c"];
#Array.map
p a.map {|item| "map_" + item}
#prints ["map_a", "map_b", "map_c"]

#Array.each
p a.each {|item| "map_" + item}
#prints ["a", "b", "c"]

Si vede che la mappa ritorna ["map_a", "map_b", "map_c"]considerando che ciascuno solo itera ma restituisce la matrice originale: ["a", "b", "c"].

Quindi ognuno viene utilizzato per elaborare un array e la mappa viene utilizzata per fare qualcosa con un array elaborato.


4

.each restituisce lo stesso array fornito inizialmente:

[1,2,3].each { |i| i + 1 }
#=> [1,2,3]

.map restituisce un nuovo array dai risultati di ogni chiamata di blocco:

[1,2,3].map { |i| i + 1 }
#=> [2,3,4]

1

Array # ogni metodo restituisce lo stesso array

a = [1,2,3,4,5]
a.object_id #70284994490700

b = a.each {|n| n + 2}
p b #[1,2,3,4,5]
b.object_id #70284994490700 <<--- it's the same as a

Il metodo Array # map restituisce un nuovo array

c = [1,2,3,4,5]
c.object_id #70219117705860

d = c.map {|n| n + 2}
p d #[3,4,5,6,7]
d.object_id #70284994343620  <<---- it's different than c

0

quando usi la mappa su un hash, esegue implicitamente il cast dell'hash su un array, quindi hai

[["d", [11, 22]], ["f", [33, 44, 55]]]

vs.each {...} restituisce solo l'ultima valutazione, che è [11, 22] per ["d", [11, 22]] e [33, 44, 55] per ["f", [ 33, 44, 55]]. Quindi, prima dell'ultimo join, l'hai fatto

[[11, 22], [33, 44, 55]]

0

Puoi anche usare mapcon bang map!che cambia l'array di origine


Questa non è una risposta alla domanda. la domanda riguarda la differenza tra each, che esegue il blocco dato e restituisce l'array originale; e map, che restituisce un array con il risultato dell'esecuzione del blocco come valori
Sampson Crowley
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.