zrozumienie Rubiego #inject / # reduce enumerable methods w mniej niż 5 minut
aby rozpocząć, ta metoda pobiera tablicę i dwa argumenty, gdy jest zdefiniowana. Można to zwizualizować w następujący sposób:
.inject { |memo, value|
#more lines of code here
}.reduce { |memo, value|
#more lines of code here
}
aby zauważyć, zmiennamemo
nazywa się tutajmemo
, aby oznaczać pamięć. Ta zmienna jest niezbędna, ponieważ przechowuje dane, które chcesz, aby ta metoda zapamiętała podczas przechodzenia przez tablicę, ale może być nazwana cokolwiek chcesz, ponieważ jest to tylko zmienna.
będę się odnosił do tego jakomemo
w całym tym wyjaśnieniu.
memo
może mieć wartość początkową, ale nie musi jej mieć. Jeżeli wartość początkowa nie jest zdefiniowana, to memo
pobierze pierwszą wartość tablicy.
### 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
zawsze zwróci pojedynczy obiekt danych — danememo
znajdują się na końcu. Biorąc to pod uwagę, memo
musi zostać zmieniona i zwrócona podczas zapętlania, w przeciwnym razie pozostanie na tej samej wartości.
teraz, gdy mamy już semantykę w dół, zamierzam przejrzeć kilka przykładów, gdy znalazłem#inject
#reduce
przydatne.
przykład 1: Użycie #inject/#reduce do zastosowania operacji numerycznej
najczęstszym sposobem użycia tej metody jest podanie tablicy liczb całkowitych i zastosowanie operacji numerycznej na całej tablicy. W tym przykładzie pokażę, jak znaleźć sumę całej tablicy.
#inject
#reduce
, zostanie zilustrowany jako taki:
.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
ponieważ jest to dość powszechny sposób użycia #inject
#reduce
, istnieje skrócona metoda, której możesz użyć, jeśli chcesz zastosować operację numeryczną w całej tablicy, podając ją w następujący sposób:
## This is for product, with no initial value stated
.inject(:*)
#=> 120 ### This is for sum, with an initial value of 5
.reduce(5, :+)
#=> 20
przykład 2: użycie #inject/ #reduce, aby znaleźć najdłuższy ciąg
w tym przykładzie, powiedzmy, że podano tablicę ciągów i musisz znaleźć najdłuższy ciąg w tej tablicy.
w tym przypadku #inject
#reduce
zostanie wyświetlony w następujący sposób:
sentences = sentences.inject{ |memo, sentence|
if memo.size < sentence.size
memo = sentence
else
memo
end
}
#=> "There are jumping lizards on the fountain"
aby to rozbić: ponieważ nie inicjujemy memo
z wartością, to zajmie pierwszy obiekt w tablicy, sentences
w tym przykładzie. Wewnątrz naszej metody mamyif
oświadczenie, które po prostu porównuje nasząmemo
długość z każdymsentence
długość.
to if
oświadczenie jest tam, gdzie dzieje się magia: jeśli sentence
jest dłuższy niż zapisany w memo
, to ponownie przypisujemy memo jako sentence
; w przeciwnym razie po prostu zwracamy tę samą wartość.
w ten sposób nasza wartość memo
będzie stale aktualizowana z dłuższymisentence
I #inject
#reduce
zwróci, że memo
zmienna na końcu.
Jeśli chcesz zobaczyć każdy krok na ilustracji, możesz to uruchomić w Repl.it zobaczyć na własne oczy.
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
}
przykład # 3: Używając # inject/#reduce, aby znaleźć najbardziej powtarzającą się liczbę w tablicy
teraz, gdy ćwiczyliśmy używanie tej metody na różne sposoby, zróbmy podobny przykład. Powiedzmy, że otrzymujesz losową tablicę liczb i chcesz dowiedzieć się, która liczba powtarza się więcej.
w tym przypadku możesz użyć#inject
#reduce
w ten sposób:
numbers = numbers.reduce { |memo, number|
if numbers.count(memo) <= numbers.count(number)
memo = number
else
memo
end
}
teraz ta logika jest podobna do tego, co zrobiliśmy w przykładzie 2, jedyną różnicą jest nasza instrukcja if, używamy #count
na naszej początkowej tablicy, aby znaleźć i zapisać, która wartość ma większą lub równą liczbę. W ten sposób zwracana jest tylko liczba, która na końcu ma największą liczbę.