Als ich vor vielen Jahren angefangen habe, Ruby zu schreiben, brauchte ich eine Weile, um den Unterschied zwischen each und map . Es wurde noch schlimmer, als ich all die anderen Enumerable und Array Methoden.
Mit Hilfe der offiziellen Dokumentation und vielen Fragen begann ich langsam zu verstehen, was diese Methoden getan haben.
Hier ist, was mich noch länger zu verstehen brauchte:
Ich hoffe, dass diese Frage kein Duplikat ist: Ich interessiere mich mehr für das "Warum?" als das "Was?" oder "Wie?", und ich denke, es könnte Ruby Newcomern helfen.
Eine Antwort tl; dr :
Wie wähle ich zwischen jedem, map, inject, each_with_index und jedem_with_object?
Verwenden Sie #each
, wenn Sie eine "generische" Iteration wünschen und sich nicht um das Ergebnis kümmern. Beispiel - Sie haben Zahlen, Sie möchten den absoluten Wert jeder einzelnen Nummer ausgeben:
Verwenden Sie #map
, wenn Sie eine neue Liste wünschen, in der jedes Element durch Transformation der ursprünglichen Elemente gebildet wird. Beispiel - Sie haben Zahlen, Sie möchten ihre Quadrate erhalten:
Verwenden Sie #inject
, wenn Sie die gesamte Liste auf einen einzelnen Wert reduzieren möchten. Beispiel - Sie haben Nummern, Sie möchten ihre Summe erhalten:
Verwenden Sie #each_with_index
in derselben Situation wie #each
, außer dass Sie auch den Index für jedes Element verwenden möchten:
Die Verwendung von #each_with_object
ist begrenzter. Der häufigste Fall ist, wenn Sie etwas ähnlich wie #inject
benötigen, aber eine neue Sammlung (im Gegensatz zu einem einzelnen Wert) möchten, die keine direkte Zuordnung des Originals ist. Beispiel - Zahlenhistogramm (Frequenzen):
Zunächst sollte das Objekt, mit dem Sie arbeiten, ein Array sein, ein Hash , ein Set , ein Bereich oder jedes andere Objekt, das auf each
reagiert. Wenn dies nicht der Fall ist, könnte es in etwas umgewandelt werden, das dies tut. Sie können each
nicht direkt auf String zum Beispiel, weil Sie angeben müssen, ob Sie über jedes Byte, Zeichen oder jede Zeile iterieren möchten / p>
%Vor%
Wenn Sie über jedes Element iterieren, etwas damit machen und das ursprüngliche Objekt nicht verändern wollen, können Sie each
. Bitte lesen Sie weiter, um zu wissen, ob Sie das wirklich sollten.
Dies ist die allgemeinste Iterationsmethode, und Sie könnten eine der anderen erwähnten Methoden damit schreiben. Wir werden tatsächlich, nur für pädagogische Zwecke. Wenn Sie in Ihrem Code ein ähnliches Muster entdecken, könnten Sie es wahrscheinlich durch die entsprechende Methode ersetzen.
Es ist grundsätzlich falsch, each
zu verwenden, es ist jedoch fast nie die beste Wahl. Es ist ausführlich und nicht Ruby-ish.
Beachten Sie, dass each
das ursprüngliche Objekt zurückgibt, aber das wird selten (nie?) benutzt. Die Logik findet innerhalb des Blocks statt und sollte das ursprüngliche Objekt nicht verändern.
Das einzige Mal, wenn ich each
verwende, ist:
Rufen Sie einfach object.to_a
auf.
Einige der unten beschriebenen Methoden (z. B. compact
, < a href="https://ruby-doc.org/core-2.0/Array.html#method-i-uniq"> uniq
) sind nur für Arrays definiert.
Wenn Sie ein Array basierend auf dem ursprünglichen Objekt erhalten möchten, können Sie map
. Das zurückgegebene Objekt hat die gleiche Größe wie das Original.
Das zurückgegebene Array wird das ursprüngliche Objekt nicht ersetzen.
Diese Methode ist sehr weit verbreitet. Es sollte der erste sein, den Sie nach Wenn Ihr ursprüngliches Objekt ein Hash ist, Sie können Sie können Sie können Sie können Sie können Gibt die Variable zurück, wie sie in der letzten Iteration definiert wurde. Sie können Er gibt die Variable zurück, die durch die letzte Iteration geändert wurde. Beachten Sie, dass die Reihenfolge der beiden Blockvariablen im Vergleich zu Wenn Ihre Variable ein Hash ist, sollten Sie diese Methode wahrscheinlich zum injizieren bevorzugen, weil Dann ist es wahrscheinlich in Ordnung, Es ist ein work in progress, und ich würde mich über Feedback freuen. Wenn es interessant genug ist und in eine Seite passt, kann ich daraus ein Flussdiagramm extrahieren. each
. collect
ist ein Synonym für %Co_de% . Stellen Sie sicher, dass nur eines von beiden in Ihren Projekten verwendet wird. Ich möchte einen modifizierten Hash basierend auf dem ursprünglichen Hash erhalten.
map
wird sowieso ein Array zurückgeben. Wenn Sie einen Hash zurück möchten: Ich möchte einige Elemente filtern.
Ich möchte nil Elemente entfernen
map
aufrufen. Es wird ein neues Array ohne die Nil-Elemente zurückgegeben. Ich möchte eine Logik schreiben, um festzustellen, ob ein Element im neuen Array
enthalten sein soll
compact
oder select
. Ich möchte doppelte Elemente aus Ihrem Array entfernen
reject
: Ich möchte über alle Elemente iterieren, während ich von 0 bis n-1
zähle
uniq
verwenden: each_with_index
gibt das ursprüngliche Objekt zurück. Ich möchte über alle Elemente iterieren, während ich eine Variable während jeder Iteration setze und sie in der nächsten Iteration verwende.
each_with_index
: inject
ist ein Synonym. Wie bei map / collect, wähle ein Schlüsselwort und behalte es. Ich möchte über alle Elemente iterieren und gleichzeitig eine Variable für jede Iteration verfügbar halten.
reduce
verwenden: each_with_object
. inject
1 zurückgibt, und es würde eine weitere Zeile in Ihrem inject-Block erfordern, um einen Hash zurückzugeben. Ich möchte etwas, das noch nicht erwähnt wurde.
h["a"]=1
;) zu verwenden. Anmerkungen:
Tags und Links ruby arrays hash enumerable