Rubys #inject / #reduce aufzählbare Methoden in weniger als 5 Minuten verstehen
Zu Beginn benötigt diese Methode ein Array und zwei Argumente, wenn sie definiert ist. Dies kann wie folgt visualisiert werden:
.inject { |memo, value|
#more lines of code here
}.reduce { |memo, value|
#more lines of code here
}
Zu beachten ist, dass die Variablememo
hier memo
für Speicher steht. Diese Variable ist wichtig, da sie speichert, an welche Daten sich diese Methode erinnern soll, während sie das Array durchläuft, aber sie kann beliebig benannt werden, da es sich nur um eine Variable handelt.
Ich werde es in dieser Erklärung alsmemo
bezeichnen.
memo
kann ein Startwert angegeben werden, aber es ist nicht erforderlich, einen zu haben. Wenn kein Startwert definiert ist, nimmt memo
den ersten Wert des Arrays.
### The starting value for memo is 5
.inject(5) { |memo, value|
#more lines of code here
}
### The starting value for memo is 1 (first value of the array)
.reduce { |memo, value|
#more lines of code here
}
#inject
#reduce
gibt immer ein einzelnes Datenobjekt zurück — die Daten memo
stehen am Ende. Davon abgesehen muss memo
geändert und zurückgegeben werden, während es in einer Schleife ausgeführt wird, da es sonst auf demselben Wert bleibt.
Nun, da wir die Semantik heruntergefahren haben, werde ich einige Beispiele durchgehen, wenn ich #inject
#reduce
nützlich fand.
Beispiel 1: Verwenden von #inject / #reduce zum Anwenden einer numerischen Operation
Diese Methode wird am häufigsten verwendet, wenn ein Array von Ganzzahlen angegeben wird und Sie eine numerische Operation auf das gesamte Array anwenden müssen. In diesem Beispiel werde ich zeigen, wie man die Summe eines ganzen Arrays findet.
#inject
#reduce
, wird als solches dargestellt:
.reduce { |memo, value|
memo += value
} ## The following is to illustrate how this method was traversed
~> 1 += 2 #memo returns 3
~> 3 += 3 #memo returns 6
~> 6 += 4 #memo returns 10
~> 10 += 5 #memo returns 15#=> 15
Da dies eine ziemlich übliche Art ist, #inject
#reduce
es gibt eine Shorthand-Methode, die Sie verwenden können, wenn Sie nur eine numerische Operation in Ihrem Array anwenden möchten, indem Sie sie folgendermaßen angeben:
## This is for product, with no initial value stated
.inject(:*)
#=> 120 ### This is for sum, with an initial value of 5
.reduce(5, :+)
#=> 20
Beispiel 2: Verwenden von #inject/ #reduce, um die längste Zeichenfolge zu finden
Angenommen, Sie erhalten ein Array von Zeichenfolgen und müssen die längste Zeichenfolge in diesem Array finden.
In diesem Fall wird #inject
#reduce
wie folgt angezeigt:
sentences = sentences.inject{ |memo, sentence|
if memo.size < sentence.size
memo = sentence
else
memo
end
}
#=> "There are jumping lizards on the fountain"
Um dies aufzuschlüsseln: Da wir memo
nicht mit einem Wert initialisieren, wird der erste Wert verwendet, der objekt im Array, sentences
in diesem Beispiel. Innerhalb unserer Methode haben wir eine if
Anweisung, die nur unsere memo
Länge mit jeder sentence
Länge vergleicht.
Diese if
Anweisung ist, wo die Magie passiert: wenn ein sentence
länger ist als das in memo
gespeicherte memo, weisen wir es neu zu sentence
; Andernfalls geben Sie einfach den gleichen Wert zurück.
Auf diese Weise wird unser memo
-Wert kontinuierlich mit der längerensentence
und #inject
#reduce
aktualisiert gibt am Ende diese memo
-Variable zurück.
Wenn Sie jeden Schritt veranschaulichen möchten, können Sie dies in ausführen Repl.it um es selbst zu sehen.
sentences = sentences.inject { |memo, sentence|
puts "Memo length is: #{memo.length}\nSentence length is: #{sentence.length}"
if memo.length < sentence.length
puts "Our sentence is longer"
memo = sentence
else
puts "Our memo is longer"
memo
end
puts "Our memo is: #{memo}\n \n"
memo
}
Beispiel #3: Verwenden von #inject/#reduce, um die sich am häufigsten wiederholende Zahl in einem Array zu finden
Nachdem wir diese Methode auf verschiedene Arten geübt haben, führen wir ein ähnliches Beispiel durch. Angenommen, Sie erhalten ein zufälliges Array von Zahlen und möchten herausfinden, welche Zahl sich mehr wiederholt.
In diesem Fall können Sie#inject
#reduce
wie folgt verwenden:
numbers = numbers.reduce { |memo, number|
if numbers.count(memo) <= numbers.count(number)
memo = number
else
memo
end
}
Nun, diese Logik ist ähnlich zu dem, was wir in Beispiel 2 gemacht haben, der einzige Unterschied ist in unserer if Anweisung, wir verwenden #count
auf unserem anfänglichen Array zu finden und zu speichern, welcher Wert eine größere oder gleiche Anzahl hat. Auf diese Weise erhalten wir nur die Zahl zurück, die am Ende die größte Anzahl hat.