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"

jedyną różnicą są przypadki użycia 1, zastosowania vs.map2 vs.each.

Co tu się stało?

user612308
źródło

Odpowiedzi:

174

Array#each wykonuje dany blok dla każdego elementu tablicy, a następnie zwraca samą tablicę.

Array#map wykonuje również dany blok dla każdego elementu tablicy, ale zwraca nową tablicę, której wartości są wartościami zwracanymi w każdej iteracji bloku.

Przykład: załóżmy, że masz tak zdefiniowaną tablicę:

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

Następnie spróbuj wykonać each:

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

Zwróć uwagę, że zwracana wartość to po prostu ta sama tablica. Kod wewnątrz eachbloku zostaje wykonany, ale obliczone wartości nie są zwracane; a ponieważ kod nie ma skutków ubocznych, ten przykład nie wykonuje żadnej użytecznej pracy.

W przeciwieństwie do tego wywołanie metody tablicy mapzwraca nową tablicę, której elementy są wartościami zwracanymi przez każdą rundę wykonywania mapbloku:

arr.map { |element| element.capitalize }
# => ["Tokyo", "London", "Rio"]
Oliwki
źródło
Doskonała odpowiedź do zrozumienia. Tylko… Zastrzeżenie: Jeśli nadużyjesz wartości zwracanej przez funkcję mapy, możesz potencjalnie zmarnować dużo pamięci.
Imran Ahmad
33

Te skutki uboczne są takie same, która jest dodanie trochę zamieszania do inżynierii odwrotnej.

Tak, oba iterują po tablicy (a właściwie po wszystkim, co miesza się w Enumerable ), ale map zwróci Array złożony z wyników bloku, podczas gdy każdy zwróci oryginalny Array.

Wartość zwracana każdego z nich to tylko oryginalna tablica i jest rzadko używana w kodzie Rubiego, ale mapa jest jednym z najważniejszych narzędzi funkcjonalnych .

Co map robi to zwraca tablicę zawierającą wyniki bloku lub metody o nazwie, która jest przekazywana. Na przykład:

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

W tym przypadku nie przekazałem bloku, a tylko a Symbol, jednak class Symbolobiekty mają to_procmetodę, która spowoduje:

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

BTW, możesz mieć trudności ze znalezieniem dokumentacji, ponieważ map jest metodą w Enumerable, podczas gdy każda (jedyna metoda wymagana przez moduł Enumerable ) jest metodą w Array .

Uwaga: implementacja mapy jest oparta na każdym z nich .

DigitalRoss
źródło
13

Oto krótkie pokazanie, czym różni się mapa od każdej z nich

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

Widać, że mapa powraca ["map_a", "map_b", "map_c"]podczas gdy każdy zaledwie iteruje ale zwraca oryginalną tablicę: ["a", "b", "c"].

Więc każdy jest używany do przetwarzania tablicy, a mapa jest używana do zrobienia czegoś z przetworzoną tablicą.

Rima
źródło
4

.each zwraca tę samą tablicę, którą podałeś na początku:

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

.map zwraca nowy Array z wyników każdego wywołania bloku:

[1,2,3].map { |i| i + 1 }
#=> [2,3,4]
pastullo
źródło
1

Tablica # każda metoda zwraca tę samą tablicę

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

Metoda Array # map zwraca nową tablicę

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
źródło
0

kiedy używasz map do hasha, niejawnie rzutuje hash na tablicę, więc masz

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

kontra każdy {...} zwraca tylko ostatnią ocenę, czyli [11, 22] dla ["d", [11, 22]] i [33, 44, 55] dla ["f", [ 33, 44, 55]]. Więc przed ostatnim dołączeniem masz

[[11, 22], [33, 44, 55]]
sawa
źródło
0

Możesz także użyć mapz bang, map!który zmienia tablicę źródłową

Aleksandr Babushkin
źródło
To nie jest odpowiedź na pytanie. pytanie dotyczy różnicy pomiędzy each, który wykonuje dany blok i zwraca oryginalną tablicę; and map, która zwraca tablicę z wynikiem wykonania bloku jako wartości
Sampson Crowley