Массив#каждый против массива#карта
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 ответов:
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, но карта один из наиболее важные функциональные инструменты.
что
mapdoes возвращает массив, который содержит результаты блока или именованного метода, который передается. Например: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 aArray#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