begrip van Ruby ‘ s #inject / #reduce enumerable methods in minder dan 5 minuten
om te beginnen, heeft deze methode een array en twee argumenten nodig wanneer deze zijn gedefinieerd. Dit kan als volgt worden gevisualiseerd:
.inject { |memo, value|
#more lines of code here
}.reduce { |memo, value|
#more lines of code here
}
om op te merken, wordt de variabelememo
hier wordt memo
genoemd om te staan voor geheugen. Deze variabele is essentieel omdat het slaat welke gegevens u wilt dat deze methode te onthouden, terwijl het doorkruist door de array, maar het kan worden genoemd alles wat je wilt, omdat het gewoon een variabele.
Ik zal het refereren alsmemo
in deze uitleg.
memo
kan een startwaarde krijgen, maar het is niet vereist om er een te hebben. Als een beginwaarde niet gedefinieerd is, dan neemt memo
de eerste waarde van de array.
### 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
geeft altijd een enkel gegevensobject terug — de gegevens memo
houdt aan het einde. Dat gezegd hebbende, memo
moet worden gewijzigd en geretourneerd als het wordt lused of anders zal het op dezelfde waarde blijven.
nu we de semantiek onder de knie hebben, ga ik enkele voorbeelden doornemen voor toen ik #inject
#reduce
nuttig vond.
Voorbeeld 1: het gebruik van #inject / # reduce om een numerieke operatie toe te passen
de meest gebruikelijke manier om deze methode te gebruiken is wanneer u een array van gehele getallen krijgt en u een numerieke operatie op de gehele array moet toepassen. In dit voorbeeld ga ik laten zien hoe je de som van een hele array kunt vinden.
#inject
#reduce
, zal geïllustreerd worden dan zo uit:
.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
Aangezien dit een vrij veel voorkomende manier om te gebruiken #inject
#reduce
, er is een verkorte methode die u kunt gebruiken als u alleen wilt toepassen op een numerieke bewerking in uw array door te stellen dat het de volgende manier:
## This is for product, with no initial value stated
.inject(:*)
#=> 120 ### This is for sum, with an initial value of 5
.reduce(5, :+)
#=> 20
Voorbeeld 2: het Gebruik van #injecteren/ #verminder de langste tekenreeks vinden
Voor dit voorbeeld, dat u wordt gegeven een array van strings en je hebt de langste tekenreeks vinden in de matrix.
voor dit geval wordt #inject
#reduce
als volgt weergegeven:
sentences = sentences.inject{ |memo, sentence|
if memo.size < sentence.size
memo = sentence
else
memo
end
}
#=> "There are jumping lizards on the fountain"
om dit op te splitsen: aangezien we memo
niet initialiseren met een waarde, zal het nodig zijn het eerste object in de array, sentences
in dit voorbeeld. Binnen onze methode hebben we een if
statement dat onze memo
lengte vergelijkt met elke sentence
lengte.
dit if
statement is waar de magie gebeurt: als een sentence
langer is dan degene die is opgeslagen in memo
dan wijzen we memo opnieuw toe aan sentence
; anders geeft u dezelfde waarde terug.
op deze manier zal onze memo
waarde continu worden bijgewerkt met de langeresentence
en #inject
#reduce
zal die memo
variabele aan het einde teruggeven.
Als u elke stap geïllustreerd wilt zien, kunt u dit uitvoeren in Repl.it om het zelf te zien.
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
}
Voorbeeld # 3: Gebruik #inject / # reduce om het meest herhalende getal in een array
te vinden nu we deze methode op verschillende manieren hebben geoefend, laten we een vergelijkbaar voorbeeld doen. Stel dat u een willekeurige reeks getallen krijgt en u wilt vinden welk getal meer herhaalt.
in dit geval kunt u#inject
#reduce
als zodanig gebruiken:
numbers = numbers.reduce { |memo, number|
if numbers.count(memo) <= numbers.count(number)
memo = number
else
memo
end
}
nu is deze logica vergelijkbaar met wat we deden in Voorbeeld 2, het enige verschil is in ons if statement, we gebruiken #count
op onze initiële array om te vinden en op te slaan welke waarde een groter of gelijk aantal heeft. Op deze manier krijgen we alleen het nummer terug dat uiteindelijk de grootste telling heeft.