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