Массив#каждый против массива#карта


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 81

6 ответов:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

вот быстрая демонстрация того, как карта отличается от каждого

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

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

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

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

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

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

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

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

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

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

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

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