2009-07-24 15 views
1

Die | m, k | Ding wirft mich irgendwie ab. Hat das etwas mit der Rangordnung zu tun? m für 0 (oder 1 in einigen Sprachen) und k für die letzte in der Array/Hash was auch immer?Also vielleicht bekomme ich nicht die Idee in Ruby, aber ich habe eine Frage zu Enumerables injizieren

Also warum setzen Leute eine Nummer in .inject()?

Oder gibt es eine einfache Möglichkeit zu lernen, wie man das verwendet und was genau es wert ist? Ausgehend von dieser Frage hoffe ich, dass Sie alle wissen, dass ich für jede Programmiersprache ziemlich noobisch bin und Ruby meine erste Wahl war.

+1

Haben Sie ein besonderes Beispiel Sie‘ D wie erklären? Kjfletchs Antwort ist gut. Wenn Sie Ihre Frage etwas erweitern, können die Leute vielleicht mehr Details liefern. – mikej

Antwort

1

Die | x, y | werden bei der Verwendung von Blöcken verwendet. Wenn die Yield-Anweisung aufgerufen wird, weisen Sie sie an, die Aufrufvariablen auf x und y abzubilden.

Schauen Sie hier Blocks and Yield

Sehen Sie hier für einen breakdown of an inject() Anruf.

5

Sie scheinen Blockargumente mit Methodenargumenten zu verwechseln.

Die Anzahl der Personen, die an die inject() -Methode übergeben werden, ist ein Methodenargument, das den Anfangswert für "m" bestimmt, wenn Sie | m, k | verwenden für den Block. Ich weiß nicht, wo du sie genannt hast, m und k, oder warum sie so genannt wurden, aber es ist sicher nicht so, weil sie für das erste und letzte Element stehen.

Es wäre einfacher, es in der Art und Weise zu betrachten, die in kjfletchs Link breakdown of an inject() beschrieben ist, wo sie stattdessen "result" und "element" heißen.

Der Wert bei der Verwendung von inject() ist die Fähigkeit, präzise zu sein. Alles, was Sie mit inject() tun möchten, könnte auch mit einem Aufruf der each() -Methode erfolgen, mit einem viel längeren Block und zusätzlichen Variablen-Deklarationen. Siehe this question and the answer, um ein Gefühl dafür zu bekommen.

6

Lassen Sie uns ein Beispiel versuchen.

numbers = [ 3, 1, 4, 1, 5, 9 ] 
sum = numbers.inject(0) do |prefix_sum, number| 
    prefix_sum + number 
end 

#inject nimmt ein Argument und einen Block. Der Block sollte zwei Werte annehmen und einen neuen Wert zurückgeben. Im obigen Beispiel lautet das Argument #inject0 und der Block lautet do |prefix_sum, number| prefix_sum + number end. Die Werte, die an den Block übergeben werden, werden zwischen den beiden | Markern benannt: prefix_sum und number.

Jeder Wert des aufzählbaren #inject wurde aufgerufen, der wiederum als zweiter Wert an den Block übergeben wird. In diesem Beispiel wird number3 sein, dann 1, dann 4, dann 1, dann 5, dann schließlich 9. In diesem Beispiel wird der Block sechsmal aufgerufen. einmal für jede Position in numbers.

Der erste an einen Block (hier prefix_sum) übergebene Wert wird normalerweise als Akku bezeichnet. Sein Anfangswert, der Wert, der beim ersten Aufruf des Blocks von #inject verwendet wird, wird durch das Argument gesetzt, das an #inject übergeben wird (in diesem Beispiel 0). Der Rückgabewert des Bausteins bestimmt den Wert des Akkumulators (prefix_sum) für den nächsten Aufruf des Bausteins.

Wenn keine weiteren Elemente zu verarbeiten sind, wird der Wert des Akkumulators zurückgegeben (und hier in sum gespeichert).

lässt So Spaziergang durch sie:

  • #inject empfängt 0 und unserem Block.
  • #inject ruft unseren Block, Binde- prefix_sum-0 (die anfängliche Akkumulatorwert) und number-3 (der erste Array-Wert).
  • unser Block berechnet 0+3 als 3 und gibt es zurück.
  • #inject ruft unseren Block, Binde- prefix_sum zu 3 (der zurückgegebene Wert) und number-1 (der zweite Array-Wert)
  • unser Block berechnet als 3+14 und gibt ihn zurück.
  • #inject ruft unseren Block, Binde- prefix_sum zu 4 (der zurückgegebene Wert) und number zu 4 (der dritten Array-Wert)
  • unser Block berechnet als 4+48 und gibt ihn zurück.
  • #inject ruft unseren Block, Binde- prefix_sum zu 8 (der zurückgegebene Wert) und number-1 (der vierte Arraywert)
  • unser Block berechnet als 8+19 und gibt ihn zurück.
  • #inject ruft unseren Block, Binde- prefix_sum zu 9 (der zurückgegebene Wert) und number-5 (der fünfte Array-Wert)
  • unser Block berechnet als 9+514 und gibt ihn zurück.
  • #inject ruft unseren Block, Binde- prefix_sum zu 14 (der zurückgegebene Wert) und number-9 (der sechste Feldwert)
  • unser Block berechnet als 14+923 und gibt ihn zurück.
  • Da es keine Array-Elemente mehr gibt, gibt #inject23 zurück, und wir binden sum an diesen Wert.

Sie können auf einer Liste von Elementen eine Operation bei Inject aussehen wie das einklammern, in diesem Beispiel caluculating:

((((((0 + 3) + 1) + 4) + 1) + 5) + 9) 

Diese Sie alle Funktionen übernehmen kann, die normalerweise arbeitet nur auf einem Paar von Argumenten, und wenden Sie es auf eine Liste an.

+0

+1 große Erklärung –

2

Wenn Sie herausfinden möchten, was eine Methode in Ruby macht, können Sie das gebündelte Tool ri verwenden (so könnten Sie "ri Enumerable.inject" eingeben, um die Dokumente zu suchen) oder Ruby-Doc suchen.In diesem Fall würden Sie see:

Kombiniert die Elemente von Enum durch Anwenden des Blocks auf einen Akkumulatorwert (Memo) und jedes Element der Reihe nach. Bei jedem Schritt wird Memo auf den vom Block zurückgegebenen Wert gesetzt. Mit dem ersten Formular können Sie einen Anfangswert für das Memo angeben. Das zweite Formular verwendet das erste Element der Auflistung als Anfangswert (und überspringt dieses Element während der Iteration).

# Sum some numbers 
(5..10).inject {|sum, n| sum + n }    #=> 45 
# Multiply some numbers 
(5..10).inject(1) {|product, n| product * n } #=> 151200 

# find the longest word 
longest = %w{ cat sheep bear }.inject do |memo,word| 
    memo.length > word.length ? memo : word 
end 
longest           #=> "sheep" 

# find the length of the longest word 
longest = %w{ cat sheep bear }.inject(0) do |memo,word| 
    memo >= word.length ? memo : word.length 
end 
longest           #=> 5 
0

Der Vollständigkeit halber: m bedeutet in der Regel Memo; k kann bedeuten Schlüssel (oft verwendet in Verbindung mit v, was bedeutet Wert). So zum Beispiel:

stuff.inject({}) { |m,(k,v)| m.merge(k.to_sym => v) } 

Ich habe auch Leute gesehen verwenden ein für Akkumulator und e für Element, wie folgt aus:

numbers.inject { |a,e| a+e }