Array#each
выполняет заданный блок для каждого элемента массива, а затем возвращает сам массив.
Array#map
также выполняет данный блок для каждого элемента массива, но возвращает новый массив, значения которого являются возвращаемыми значениями каждой итерации блока.
Пример: предположим, что у вас есть массив, определенный таким образом:
arr = ["tokyo", "london", "rio"]
Затем попробуйте выполнить each
:
arr.each { |element| element.capitalize }
Обратите внимание, что возвращаемое значение - это просто тот же массив. Код внутри each
блока выполняется, но вычисленные значения не возвращаются; и поскольку код не имеет побочных эффектов, этот пример не выполняет никакой полезной работы.
Напротив, вызов map
метода массива возвращает новый массив, элементы которого являются возвращаемыми значениями каждого раунда выполнения map
блока:
arr.map { |element| element.capitalize }
Эти побочные эффекты такие же , которые добавляют некоторую путаницу в вашу обратную инженерию.
Да, оба перебирают массив (фактически, все, что смешивается в 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, ...]
Кстати, вам может быть сложно найти документацию, потому что карта - это метод в Enumerable а каждый (один метод, требуемый модулем Enumerable ) - это метод в Array .
Небольшое примечание: реализация карты основана на каждом .
источник
Вот небольшая демонстрация того, чем карта отличается от каждого
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]
источник
Массив # каждый метод возвращает один и тот же массив
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
источник
когда вы используете карту для хэша, он неявно преобразует хеш в массив, поэтому у вас есть
[["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]]
источник
Вы также можете использовать
map
с Bang,map!
который изменяет исходный массивисточник
each
, который выполняет данный блок и возвращает исходный массив; иmap
, который возвращает массив с результатом выполнения блока в виде значений