Articles

Understanding Ruby ’ s #inject / # reduce enumerable methods in under 5 minutes

för att starta tar denna metod en array och två argument när de definieras. Detta kan visualiseras som följande:

.inject { |memo, value| 
#more lines of code here
}.reduce { |memo, value|
#more lines of code here
}

Observera att variabelnmemo här kallas memo för att stå för minne. Denna variabel är viktig eftersom den lagrar vilka data du vill att den här metoden ska komma ihåg medan den går igenom hela matrisen, men den kan namnges vad du vill eftersom det bara är en variabel.

Jag kommer att hänvisa till det sommemo genom hela denna förklaring.

memo kan ges ett startvärde men det är inte nödvändigt att ha ett. Om ett startvärde inte är definierat tar memo det första värdet i 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#reducereturnerar alltid ett enda dataobjekt — data memo håller i slutet. Med det sagt, memo måste ändras och returneras när den slingras, annars kommer den att förbli på samma värde.

Nu när vi har semantiken nere, kommer jag att springa igenom några exempel för när jag hittade #inject#reduce användbar.

exempel 1: Använda #inject / #reduce för att tillämpa en numerisk operation

det vanligaste sättet att använda den här metoden är när du får en rad heltal och du måste tillämpa en numerisk operation på hela matrisen. I det här exemplet ska jag visa hur man hittar summan av en hel array.

#inject#reduce , kommer att illustreras 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

eftersom detta är ett ganska vanligt sätt att använda #inject#reduce , det finns en stenografi metod som du kan använda om du bara vill tillämpa en numerisk operation i hela din array genom att ange det på följande sätt:

## This is for product, with no initial value stated
.inject(:*)
#=> 120 ### This is for sum, with an initial value of 5
.reduce(5, :+)
#=> 20

exempel 2: Använda #inject/ #reduce för att hitta den längsta strängen

För det här exemplet, säg att du får en rad strängar och du måste hitta den längsta strängen i den arrayen.

För det här fallet kommer #inject#reduce att visas så här:

sentences = sentences.inject{ |memo, sentence| 
if memo.size < sentence.size
memo = sentence
else
memo
end
}
#=> "There are jumping lizards on the fountain"

för att bryta ner detta: eftersom vi inte initierar memo med en värde, det kommer att ta det första objektet i matrisen, sentences I det här exemplet. Inuti vår metod har vi ettif uttalande som bara jämför vårmemo längd till varjesentence längd.

dettaif uttalande är där magin händer: om en sentence är längre än den som lagras i memo då vi åter tilldela memo vara sentence; annars bara returnera samma värde.

På så sätt uppdateras vårtmemo värde kontinuerligt med det längresentence och#inject#reduce returnerar detmemo variabel i slutet.

Om du vill se varje steg illustrerat kan du köra detta i Repl.it att se själv.

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
}

exempel # 3: Använda #inject/ # reduce för att hitta det mest upprepande numret i en array

Nu när vi övade att använda denna metod på olika sätt, låt oss göra ett liknande exempel. Säg att du får en slumpmässig uppsättning siffror och du vill hitta vilket nummer som upprepas mer.

i det här fallet kan du använda#inject#reduce som så:

numbers = numbers.reduce { |memo, number|
if numbers.count(memo) <= numbers.count(number)
memo = number
else
memo
end
}

nu liknar denna logik vad vi gjorde i Exempel 2, den enda skillnaden är i vårt if-uttalande, Vi använder #count på vår ursprungliga array för att hitta och lagra vilket värde som har ett större eller lika antal. På så sätt returneras vi bara det nummer som har störst räkning i slutändan.