Array # each vs. Array # map

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"

Der einzige Unterschied besteht darin, dass Fall 1 vs.mapund Fall 2 verwendet werdenvs.each .

Was ist hier passiert?

user612308
quelle

Antworten:

174

Array#each führt den angegebenen Block für jedes Element des Arrays aus und gibt dann das Array selbst zurück.

Array#map führt auch den angegebenen Block für jedes Element des Arrays aus, gibt jedoch ein neues Array zurück, dessen Werte die Rückgabewerte jeder Iteration des Blocks sind.

Beispiel: Angenommen, Sie haben ein Array wie folgt definiert:

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

Versuchen Sie dann Folgendes auszuführen each:

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

Beachten Sie, dass der Rückgabewert einfach dasselbe Array ist. Der Code im eachBlock wird ausgeführt, die berechneten Werte werden jedoch nicht zurückgegeben. und da der Code keine Nebenwirkungen hat, führt dieses Beispiel keine nützliche Arbeit aus.

Im Gegensatz dazu gibt der Aufruf der Array- mapMethode ein neues Array zurück, dessen Elemente die Rückgabewerte jeder Ausführungsrunde des mapBlocks sind:

arr.map { |element| element.capitalize }
# => ["Tokyo", "London", "Rio"]
Oliven
quelle
Perfekte Antwort zu verstehen. Nur ein .. Haftungsausschluss: Wenn Sie den Rückgabewert der Kartenfunktion überbeanspruchen, können Sie möglicherweise viel Speicher verschwenden.
Imran Ahmad
33

Die Nebenwirkungen sind die gleichen, was Ihr Reverse Engineering verwirrt.

Ja, beide iterieren über das Array (tatsächlich über alles, was sich in Enumerable mischt ), aber map gibt ein Array zurück, das aus den Blockergebnissen besteht, während jedes nur das ursprüngliche Array zurückgibt .

Der Rückgabewert jedes Arrays ist nur das ursprüngliche Array und wird im Ruby-Code selten verwendet, aber Map ist eines der wichtigsten funktionalen Werkzeuge .

Sie mapgeben ein Array zurück, das die Ergebnisse des übergebenen Blocks oder der benannten Methode enthält. Beispielsweise:

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

In diesem Fall habe ich keinen Block übergeben, sondern nur einen Symbol. class SymbolObjekte haben jedoch eine to_procMethode, die Folgendes ergibt:

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

Übrigens fällt es Ihnen möglicherweise schwer, die Dokumentation zu finden, da map eine Methode in Enumerable ist, während jede (die eine vom Enumerable- Modul erforderliche Methode ) eine Methode in Array ist .

Als Trivia-Hinweis: Die Kartenimplementierung basiert auf jedem .

DigitalRoss
quelle
13

Hier ist eine kurze Demo, wie sich die Karten von den einzelnen unterscheiden

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

Sie sehen, dass die Map zurückkehrt, ["map_a", "map_b", "map_c"]während jede nur iteriert, aber das ursprüngliche Array zurückgibt : ["a", "b", "c"].

Jedes wird also zur Verarbeitung eines Arrays verwendet, und die Karte wird verwendet, um etwas mit einem verarbeiteten Array zu tun.

Rima
quelle
4

.each Gibt dasselbe Array zurück, das Sie ursprünglich bereitgestellt haben:

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

.map Gibt aus den Ergebnissen jedes Blockaufrufs ein neues Array zurück:

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

Array # Jede Methode gibt dasselbe Array zurück

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

Die Array # Map-Methode gibt ein neues Array zurück

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
user3007294
quelle
0

Wenn Sie die Zuordnung zu einem Hash verwenden, wird der Hash implizit in ein Array umgewandelt

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

vs.each {...} gibt Ihnen nur die letzte Bewertung zurück, nämlich [11, 22] für ["d", [11, 22]] und [33, 44, 55] für ["f", [ 33, 44, 55]]. Also vor dem letzten Join haben Sie

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

Sie können auch mapmit Bang verwenden map!, um das Quell-Array zu ändern

Aleksandr Babuschkin
quelle
Dies ist keine Antwort auf die Frage. Die Frage betrifft den Unterschied zwischen each, der den angegebenen Block ausführt und das ursprüngliche Array zurückgibt. und map, das ein Array mit dem Ergebnis der Ausführung des Blocks als Werte zurückgibt
Sampson Crowley