metoda iniekcji: wyjaśniona
dzisiaj przyjrzymy się metodzie inject Ruby (#inject). Jako każdy, kto jest na tyle daleko w swojej podróży, aby dowiedzieć się więcej o kodowaniu, wiesz, że języki są pełne mylących, niesamowitych metod i funkcji. Ostatnio natknąłem się na jedną z tych mylących, i jak się nauczyłem, niesamowitych metod, wstrzykiwania. Próbowałem zsumować tablicę liczb całkowitych i błędnie myślałem, że ruby ma natywną metodę # sum, ale nie miałem takiego szczęścia. Więc, musiałem googlować i znalazłem # inject .
metoda #inject działa tak samo jak metoda #reduce i są one uważane za aliasy. Te metody enumeratora mogą przyjmować zakres lub tablicę liczb i mogą opcjonalnie otrzymać blok. Po wywołaniu metoda inject przekaże każdy element i zgromadzi każdy po kolei.
.inject(:+) => (((3 + 6) + 10) + 13) => 32
lub
.inject {|sum, number| sum + number} =>|3, 6| 3 + 6 => 9
=>|9, 10| 9 + 10 =>19
aby jeszcze bardziej to rozłożyć, inject pobiera pierwszy element w kolekcji i używa go jako podstawowej 'sumy’. Następnie bierze następny element (lub drugi element w tablicy) i dodaje je do siebie. Następnie metoda przypisuje ten wynik do 'sumy’ i dodaje do następnego elementu w zbiorze, aż wszystkie elementy zostaną przepuszczone przez blok. W tym przypadku 'suma’ jest tym, co nazywamy akumulatorem – ponieważ gromadzi wartości. Zwracana wartość będzie sumą wszystkich elementów w kolekcji.
ta metoda jest ciekawa, ponieważ można również przekazać jej domyślną wartość dla akumulatora. Patrz poniżej:
.inject(0, :+) => 32.inject(0) {|sum, number| sum + number} => 19
tutaj podajesz metodzie wartość początkową dla akumulatora, ponieważ przekazałem ją zerem, metoda doda pierwszy element kolekcji do zera przed przejściem do dodania drugiego i trzeciego elementu w kolekcji.
skoro już wiemy jak dodawać wartości ze zbiorów… przyjrzyjmy się innym zastosowaniom #inject.
budowanie skrótów:
#Inject może być bardzo potężne poza dodawaniem wartości razem. Załóżmy, że masz dane lub wartość zwracaną, która jest tablicą tablic zawierających klucze i wartości (np.]). Najprawdopodobniej będziesz chciał, aby były to pary klucz: wartość w hashu. Wstrzyknięcie może bardzo szybko i elegancko pomóc w tym.
, ].inject({}) do |result, element|
result = element.last
result
end
#=> {:student=>"Terrance Koar", :course=>"Web Dev"}
w tym przykładzie zaczynamy od tablicy tablic zawierających pary klucz i wartość. Kiedy wywołamy inject i pass w argumencie pustego hasha, który będzie działał jako akumulator (lub w tym przypadku 'wynik’). Następnie metoda przechodzi przez każdy element i wstrzykuje go do hasha za pomocą dostarczonego bloku. Blok przypisuje klucz, który pojawi się jako pierwszy, jako klucz w nowym hashu i ustawia wartość równą drugiemu elementowi w zagnieżdżonej tablicy. Inną rzeczą, na którą należy zwrócić uwagę, jest to, że wartość zwracana przez inject jest następnym wynikiem (zazwyczaj sumą liczb całkowitych). Ponieważ chcemy nasz hash, musimy jawnie zwrócić hash 'result’.
dodatkowo, inject może być użyty do konwersji typów danych za pomocą innych fajnych metod-nawet podczas budowania nowego skrótu!
, ].inject({}) do |result, element|
result = element.last.upcase
result
end
# => {"student"=>"TERRANCE KOAR", "course"=>"WEB DEV"}OR, ].inject({}) do |result, element|
result = element.last.split
result
end# => {"student"=>, "course"=>}
wstrzykiwanie nie kończy się jednak na tym. Może również filtrować i budować nową tablicę!
.inject() do |result, element|
result << element.to_s if element > 9
result
end# =>
tutaj przekazujemy wartość początkową pustej tablicy. Pierwszym elementem pomiędzy / / będzie zawsze 'wynik’ lub akumulator w bloku. Tak więc, gdy wynik jest równy pustej tablicy, możemy wstawić dowolny element, który przechodzi przez nasz filtr, w tym przypadku, jeśli element jest większy niż 9. Ponownie, ponieważ wartość zwracana przez inject jest kolejnym wynikiem, musimy jawnie zwrócić wynik.