Articles

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#reducegibt 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.