Forstå Ruby ‘ s # inject / # reduser enumerable metoder på under 5 minutter
for å starte, tar denne metoden en matrise og to argumenter når definert. Dette kan visualiseres som følgende:
.inject { |memo, value|
#more lines of code here
}.reduce { |memo, value|
#more lines of code here
}
for å merke seg, variabelenmemo
her kalles memo
å stå for minne. Denne variabelen er viktig fordi den lagrer hvilke data du vil at denne metoden skal huske mens den går gjennom hele arrayet, men det kan bli kalt alt du vil ha, siden det bare er en variabel.
jeg vil referere til det som memo
gjennom denne forklaringen.
memo
kan gis en startverdi, men det er ikke nødvendig å ha en. Hvis en startverdi ikke er definert, tar memo
den første verdien av matrisen.
### 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
vil alltid returnere et enkelt dataobjekt — dataene memo
holder på slutten. Når det er sagt, memo
må endres og returneres når den blir sløyfet, ellers vil den forbli på samme verdi.
Nå som vi fikk semantikken ned, skal jeg løpe gjennom noen eksempler for når jeg fant#inject
#reduce
nyttig.
Eksempel 1: Bruk #inject / # reduser for å bruke en numerisk operasjon
den vanligste måten å bruke denne metoden på er når du får en rekke heltall, og du må bruke en numerisk operasjon på hele arrayet. I dette eksemplet skal jeg vise hvordan du finner summen av en hel matrise.
#inject
#reduce
, vil bli illustrert som sådan:
.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
Siden dette er en ganske vanlig måte å bruke #inject
#reduce
, det er en shorthand metode du kan bruke hvis du bare vil bruke en numerisk operasjon i hele arrayet ditt ved å si det på følgende måte:
## This is for product, with no initial value stated
.inject(:*)
#=> 120 ### This is for sum, with an initial value of 5
.reduce(5, :+)
#=> 20
eksempel 2: bruk #inject/ #reduser for å finne Den Lengste strengen
for dette eksemplet, si at du får en rekke strenger, og du må finne den lengste strengen i den arrayen.
for dette tilfellet vil #inject
#reduce
vises slik:
sentences = sentences.inject{ |memo, sentence|
if memo.size < sentence.size
memo = sentence
else
memo
end
}
#=> "There are jumping lizards on the fountain"
for å bryte dette ned: siden vi ikke initialiserer memo
med en verdi, det kommer til å ta det første objektet i arrayet, sentences
i dette eksemplet. Innenfor vår metode har vi enif
setning som bare sammenligner vår memo
lengde til hver sentence
lengde.
Dette if
setningen er hvor magien skjer: hvis en sentence
er lengre enn den som er lagret i memo
så tilordner vi memo til å være sentence
; ellers returnerer vi bare samme verdi.
på denne måten vil vårmemo
verdien oppdateres kontinuerlig med den lengresentence
og#inject
#reduce
vil returnere detmemo
variabel til slutt.
hvis du vil se hvert trinn illustrert, kan du kjøre dette i Repl.it å se selv.
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
}
Eksempel # 3: Bruk #inject / # reduser for å finne det mest gjentatte tallet i en matrise
Nå som vi praktiserte å bruke denne metoden på forskjellige måter, la oss gjøre et lignende eksempel. Si at du får et tilfeldig utvalg av tall, og du vil finne hvilket nummer som gjentar mer.
for dette tilfellet kan du bruke #inject
#reduce
som så:
numbers = numbers.reduce { |memo, number|
if numbers.count(memo) <= numbers.count(number)
memo = number
else
memo
end
}
nå er denne logikken lik det Vi gjorde I Eksempel 2, den eneste forskjellen er i vår if-setning, vi bruker #count
på vår første array for å finne og lagre hvilken verdi som har en større eller lik telling. På denne måten returneres vi bare nummeret som har størst telling til slutt.