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"

a única diferença é o caso 1 usa vs.map, o caso 2 usa vs.each.

O que aconteceu aqui?

user612308
fonte

Respostas:

174

Array#each executa o bloco fornecido para cada elemento da matriz e, a seguir, retorna a própria matriz.

Array#map também executa o bloco fornecido para cada elemento da matriz, mas retorna uma nova matriz cujos valores são os valores de retorno de cada iteração do bloco.

Exemplo: suponha que você tenha uma matriz definida assim:

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

Em seguida, tente executar each:

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

Observe que o valor de retorno é simplesmente o mesmo array. O código dentro do eachbloco é executado, mas os valores calculados não são retornados; e como o código não tem efeitos colaterais, este exemplo não executa nenhum trabalho útil.

Em contraste, chamar o mapmétodo da matriz retorna uma nova matriz cujos elementos são os valores de retorno de cada rodada de execução do mapbloco:

arr.map { |element| element.capitalize }
# => ["Tokyo", "London", "Rio"]
Azeitonas
fonte
Resposta perfeita para entender. Apenas um .. Aviso de isenção: se você usar demais o valor de retorno da função de mapa, poderá desperdiçar muita memória.
Imran Ahmad
33

Os efeitos colaterais são os mesmos, o que confunde sua engenharia reversa.

Sim, ambos iteram sobre o array (na verdade, sobre qualquer coisa que se misture em Enumerable ), mas map retornará um Array composto dos resultados do bloco, enquanto cada um retornará apenas o Array original.

O valor de retorno de cada um é apenas o array original e raramente é usado no código Ruby, mas map é uma das ferramentas funcionais mais importantes .

O que mapfaz é retornar um array que contém os resultados do bloco ou método nomeado que é passado. Por exemplo:

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

Neste caso, não passei um bloco, mas apenas um Symbol, no entanto, os class Symbolobjetos têm um to_procmétodo que resultará em:

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

BTW, você pode estar tendo dificuldade em encontrar a documentação porque map é um método em Enumerable, enquanto cada (o único método exigido pelo módulo Enumerable ) é um método em Array .

Como uma curiosidade: a implementação do mapa é baseada em cada um .

DigitalRoss
fonte
13

Aqui está uma rápida demonstração de como o mapa difere de cada

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

Você vê que o mapa retornos ["map_a", "map_b", "map_c"]Considerando que cada apenas repete, mas retorna a matriz original: ["a", "b", "c"].

Portanto, cada um é usado para processar um array e map é usado para fazer algo com um array processado.

Rima
fonte
4

.each retorna a mesma matriz que você forneceu inicialmente:

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

.map retorna um novo Array com os resultados de cada chamada em bloco:

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

Array # cada método retorna o mesmo 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

O método Array # map retorna uma nova 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
user3007294
fonte
0

quando você usa map para um hash, ele converte implicitamente o hash em uma matriz, então você tem

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

vs.each {...} apenas retorna a última avaliação, que é [11, 22] para ["d", [11, 22]] e [33, 44, 55] para ["f", [ 33, 44, 55]]. Então, antes da última junção, você tem

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

Você também pode usar mapcom estrondo map!esse array de mudança de origem

Aleksandr Babushkin
fonte
Esta não é uma resposta à pergunta. a questão é sobre a diferença entre each, que executa o bloco dado e retorna o array original; e map, que retorna uma matriz com o resultado da execução do bloco como valores
Sampson Crowley