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