Articles

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ć, zmiennamemonazywa 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#reducezawsze 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 memoz 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ę.