Array # cada uno frente al mapa de Array #

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"

La única diferencia son los usos del caso 1 y los usos del vs.mapcaso 2 vs.each.

¿Que pasó aquí?

user612308
fuente

Respuestas:

174

Array#each ejecuta el bloque dado para cada elemento de la matriz, luego devuelve la matriz en sí.

Array#map también ejecuta el bloque dado para cada elemento de la matriz, pero devuelve una nueva matriz cuyos valores son los valores de retorno de cada iteración del bloque.

Ejemplo: suponga que tiene una matriz definida así:

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

Entonces intente ejecutar each:

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

Tenga en cuenta que el valor de retorno es simplemente la misma matriz. El código dentro del eachbloque se ejecuta, pero los valores calculados no se devuelven; y como el código no tiene efectos secundarios, este ejemplo no realiza ningún trabajo útil.

Por el contrario, llamar al mapmétodo de la matriz devuelve una nueva matriz cuyos elementos son los valores de retorno de cada ronda de ejecución del mapbloque:

arr.map { |element| element.capitalize }
# => ["Tokyo", "London", "Rio"]
Olivos
fuente
Respuesta perfecta para entender. Solo un .. Descargo de responsabilidad: si abusa del valor de retorno de la función de mapa, puede desperdiciar mucha memoria.
Imran Ahmad
33

Los efectos secundarios son los mismos, lo que agrega cierta confusión a su ingeniería inversa.

Sí, ambos iteran sobre la matriz (en realidad, sobre cualquier cosa que se mezcle en Enumerable ) pero el mapa devolverá una matriz compuesta por los resultados del bloque, mientras que cada una simplemente devolverá la matriz original.

El valor de retorno de cada uno es solo la matriz original y rara vez se usa en el código Ruby, pero el mapa es una de las herramientas funcionales más importantes .

Lo que maphace es devolver una matriz que contiene los resultados del bloque o método nombrado que se pasa. Por ejemplo:

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

En este caso, no pasé un bloque sino solo un Symbol, sin embargo, los class Symbolobjetos tienen un to_procmétodo que dará como resultado:

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

Por cierto, es posible que tenga dificultades para encontrar la documentación porque map es un método en Enumerable, mientras que cada (el único método requerido por el módulo Enumerable ) es un método en Array .

Como nota de trivia: la implementación del mapa se basa en cada uno .

DigitalRoss
fuente
13

Aquí hay una demostración rápida de cómo se diferencia el mapa de cada uno

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"]

Se ve que el mapa rendimientos ["map_a", "map_b", "map_c"]mientras que cada iteración sólo pero devuelve la matriz original: ["a", "b", "c"].

Entonces, cada uno se usa para procesar una matriz y el mapa se usa para hacer algo con una matriz procesada.

Rima
fuente
4

.each devuelve la misma matriz que proporcionó inicialmente:

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

.map devuelve una nueva matriz a partir de los resultados de cada llamada de bloque:

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

Array # cada método devuelve la misma matriz

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

El método de mapa de matriz # devuelve una nueva matriz

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
usuario3007294
fuente
0

cuando usa map to a hash, implícitamente lanza el hash a una matriz, por lo que tiene

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

frente a cada {...} solo le devuelve la última evaluación, que es [11, 22] para ["d", [11, 22]] y [33, 44, 55] para ["f", [ 33, 44, 55]]. Entonces, antes de la última unión, tienes

[[11, 22], [33, 44, 55]]
sawa
fuente
0

También podría usar mapcon bang map!esa matriz de fuente de cambio

Aleksandr Babushkin
fuente
Esta no es una respuesta a la pregunta. la pregunta es sobre la diferencia entre each, que ejecuta el bloque dado y devuelve la matriz original; y map, que devuelve una matriz con el resultado de ejecutar el bloque como valores
Sampson Crowley