web-dev-qa-db-fra.com

Array # each vs. Array # map

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"

la seule différence est que le cas 1 utilise vs.map, le cas 2 utilise vs.each.

Que s'est-il passé ici?

85
user612308

Array#each exécute le bloc donné pour chaque élément du tableau, puis retourne le tableau lui-même.

Array#map exécute également le bloc donné pour chaque élément du tableau, mais renvoie un nouveau tableau dont les valeurs sont les valeurs de retour de chaque itération du bloc.

Exemple: supposons que vous ayez un tableau défini ainsi:

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

Puis essayez d’exécuter each:

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

Notez que la valeur de retour est simplement le même tableau. Le code à l'intérieur du bloc each est exécuté, mais les valeurs calculées ne sont pas renvoyées. et comme le code n'a pas d'effets secondaires, cet exemple n'effectue aucun travail utile.

En revanche, l'appel de la méthode map du tableau renvoie un nouveau tableau dont les éléments sont les valeurs de retour de chaque cycle d'exécution du bloc map:

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

Les effets secondaires } sont identiques, ce qui ajoute de la confusion à votre ingénierie inverse.

Oui, les deux parcourent le tableau (en fait, tout ce qui se mélange dans Enumerable ) mais map renverra un tableau composé des résultats du bloc tant que each renverra simplement le tableau d'origine.

La valeur de retour de each n'est que le tableau d'origine et est rarement utilisée dans le code Ruby, mais map est l'un des outils fonctionnels les plus importants). .

map renvoie un tableau contenant les résultats du bloc ou de la méthode nommée transmis. Par exemple:

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

Dans ce cas, je n'ai pas passé de bloc mais juste une variable Symbol. Cependant, les objets class Symbol ont une méthode to_proc qui entraîne:

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

En passant, vous aurez peut-être de la difficulté à trouver la documentation car map est une méthode dans Enumerable alors que each (la seule méthode requise par le module Enumerable) est une méthode dans Array.

Remarque: la mise en œuvre de map est basée sur each.

31
DigitalRoss

Voici une démonstration rapide de la différence entre les cartes.

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

Vous voyez que la carte retourne ["map_a", "map_b", "map_c"] alors que chacune itère simplement mais renvoie le tableau d'origine: ["a", "b", "c"].

Donc, chacun est utilisé pour traiter un tableau et la carte est utilisée pour faire quelque chose avec un tableau traité.

12
Rima

.each renvoie le même tableau que celui que vous aviez initialement fourni:

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

.map renvoie un nouveau tableau à partir des résultats de chaque appel de bloc:

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

lorsque vous utilisez la carte vers un hachage, il jette implicitement le hachage sur un tableau, de sorte que vous avez

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

vs.each {...} ne vous renvoie que la dernière évaluation, qui est [11, 22] pour ["d", [11, 22]] et [33, 44, 55] pour ["f", [ 33, 44, 55]]. Donc, avant la dernière jointure, vous avez

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

Tableau # chaque méthode retourne le même tableau

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

La méthode Array # map renvoie un nouveau tableau

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
user3007294