Массив # по сравнению с массивом # map

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.

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

Ответ 1

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

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

Пример: предположим, что вы определили массив таким образом:

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

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

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

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

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

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

Ответ 2

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

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

Возвращаемое значение each является только исходным массивом и редко используется в коде 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, в то время как каждый (один метод, требуемый модулем Enumerable) является методом в массиве.

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

Ответ 3

Здесь приведена краткая демонстрация того, как карта отличается от каждой

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

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

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

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

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

Ответ 5

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

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

Ответ 6

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

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 the same as a

Метод массива # 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 different than c