Массив # каждый против карты Массив # - PullRequest
87 голосов
/ 10 марта 2011
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"

единственное отличие - случай 1 использует vs.map, случай 2 использует vs.each.

Что здесь произошло?

Ответы [ 6 ]

169 голосов
/ 10 марта 2011

Array#each выполняет данный блок для каждого элемента массива, затем возвращает сам массив.

Array#map также выполняет данный блок для каждого элемента массива, но возвращает новый массив, чейзначения являются возвращаемыми значениями каждой итерации блока.

Пример: предположим, что у вас есть определенный массив:

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

Затем попробуйте выполнить each:

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

Обратите внимание, что возвращаемое значение - это просто тот же массив.Код внутри блока each выполняется, но вычисленные значения не возвращаются;и поскольку код не имеет побочных эффектов, этот пример не выполняет никакой полезной работы.

Напротив, вызов метода map массива возвращает новый массив, элементы которого являются возвращаемыми значениями каждого раунда выполнения * 1018.* блок:

arr.map { |element| element.capitalize }
# => ["Tokyo", "London", "Rio"]
33 голосов
/ 19 апреля 2011

побочные эффекты одинаковы, что добавляет путаницу вашему реверс-инжинирингу.

Да, оба перебирают массив (фактически, все, что смешивается в *)1006 * Enumerable ), но map вернет массив, состоящий из результатов блока, тогда как каждый просто вернетисходный массив.

Возвращаемое значение каждый является просто исходным массивом и редко используется в коде Ruby, но map является одним из наиболее важных функциональных инструментов .

Что делает map, это возвращает массив, который содержит результаты переданного блока или именованного метода.Например:

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

В этом случае я пропустил не блок, а просто Symbol, однако у class Symbol объектов есть метод to_proc, который приведет к:

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

Кстати, вам может быть трудно найти документацию, потому что map - это метод в Enumerable , а каждый (один метод, требуемый для (перечислимый модуль) - это метод в Массив .

В качестве заметки: реализация map основана на каждая .

13 голосов
/ 19 мая 2014

Вот краткая демонстрация того, как карта отличается от каждой

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

Вы видите, что карта возвращает ["map_a", "map_b", "map_c"], тогда как каждая просто повторяет, но возвращает исходный массив: ["a", "b", "c"].

Таким образом, каждый из них используется для обработки массива, а карта используется для обработки чего-либо с обработанным массивом.

4 голосов
/ 23 апреля 2014

.each возвращает тот же массив, который вы указали изначально:

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

.map возвращает новый массив из результатов каждого вызова блока:

[1,2,3].map { |i| i + 1 }
#=> [2,3,4]
0 голосов
/ 02 ноября 2017

Массив # каждый метод возвращает один и тот же массив

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

Array # map метод возвращает новый массив

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 голосов
/ 10 марта 2011

когда вы используете map для хеша, он неявно преобразует хеш в массив, поэтому у вас есть

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

vs.each {...} возвращает вам только последнюю оценку, которая составляет [11, 22] для ["d", [11, 22]] и [33, 44, 55] для ["f ", [33, 44, 55]]. Итак, перед последним присоединением у вас есть

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