Масив # кожен проти масиву # карта


92
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.

Що тут сталося?

Відповіді:


174

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

Ідеальна відповідь для розуміння. Просто .. Застереження: Якщо ви надмірно використаєте повернене значення функції map, ви можете втратити багато пам'яті.
Імран Ахмад,

33

Ці побічні ефекти такі ж , які додають деяку плутанину в вашу зворотну інженерію.

Так, обидва ітерації над масивом (насправді, над усім, що змішується в Enumerable ), але map поверне масив, що складається з результатів блоку, тоді як кожен просто поверне вихідний масив.

Повернене значення кожного - це лише вихідний масив і рідко використовується в коді Ruby, але map є одним з найважливіших функціональних інструментів .

Що mapповертає масив, який містить результати переданого блоку або іменованого методу. Наприклад:

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

У цьому випадку я не передав блок, а лише a Symbol, однак class Symbolоб'єкти мають to_procметод, який призведе до:

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

До речі, можливо, вам важко знайти документацію, оскільки map - це метод у Enumerable, тоді як кожен (один метод, який вимагає модуль Enumerable ) - це метод у Array .

Як зауваження у дрібниці: реалізація карти базується на кожному .


13

Ось коротка демонстрація того, як карта відрізняється від кожної

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

Отже, кожен використовується для обробки масиву, а map використовується для виконання чогось із обробленим масивом.


4

.each повертає той самий масив, який ви надали спочатку:

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

.map повертає новий масив із результатів кожного виклику блоку:

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

1

Масив # кожен метод повертає той самий масив

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

0

коли ви використовуєте карту для хешу, вона неявно передає хеш у масив, отже, у вас є

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

0

Ви також можете використовувати mapз вибухом, map!що змінюють вихідний масив


Це не відповідь на запитання. питання полягає в різниці між each, який виконує даний блок і повертає вихідний масив; і map, який повертає масив із результатом виконання блоку як значення
Sampson Crowley
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.