Spis treściKliknij link, aby przejść do wybranego miejsca
Ta treść została automatycznie przetłumaczona z ukraińskiego.
Metoda map jest jedną z najczęściej używanych metod w Ruby, która służy do przetwarzania kolekcji. Pozwala zastosować blok kodu do każdego elementu kolekcji i zwrócić nową kolekcję z wynikami wykonania bloku. W rzeczywistości to wszystko, co musisz wiedzieć. Jednak każda informacja przyswajana jest lepiej nie na abstrakcjach, a na prostych i realnych przykładach. Przyjrzyjmy się więc metodzie map nieco bliżej.
Jak działa map
Metoda map przyjmuje blok, który jest wykonywany dla każdego elementu kolekcji. Wyniki wykonania tego bloku są zbierane w nową tablicę, która jest zwracana przez metodę map.
Wykonamy zwiększenie każdego elementu tablicy o 1 (inkrementacja)
numbers = [1, 2, 3, 4, 5]
incremented_numbers = numbers.map { |n| n + 1 }
incremented_numbers
Wynik
=> [2, 3, 4, 5, 6]
Uproszczając:Mamy zmienną numbers, która zawiera tablicę elementów (kolekcję elementów) [1, 2, 3, 4, 5].Następnie tworzymy zmienną incremented_numbers i zapisujemy w niej wynik wykonania metody map.
Przyjrzyjmy się konstrukcji map:
numbers.map { |n| n + 1 }
# numbers - nasza zmienna (kolekcja)
# .map - wywołanie metody na zmiennej
# { |n| n + 1 } - blok, który będzie wykonany dla każdego elementu kolekcji
Tu musimy przyjrzeć się samemu blokowi:
{ |n| n + 1 }
- {} - klamry: To ciało bloku, w którym znajduje się kod, który będzie wykonany dla każdego elementu tablicy.
- |n| - zmienna: To parametr bloku. Każdy element tablicy jest przekazywany do tej zmiennej jeden po drugim.
- n + 1: To wyrażenie, które jest wykonywane dla każdego elementu. Dodaje 1 do wartości zmiennej n.
Kiedy wykonujemy numbers.map { |n| n + 1 }, oto co się dzieje:
Dla pierwszego elementu 1:
- n staje się 1
- Wykonywane jest 1 + 1
- Wynik 2 dodawany jest do nowej tablicy
Dla drugiego elementu 2:
- n staje się 2
- Wykonywane jest 2 + 1
- Wynik 3 dodawany jest do nowej tablicy
I tak dalej dla każdego elementu tablicy. Nową tablicę zapisujemy w zmiennej incremented_numbers i sprawdzamy jej zawartość
numbers = [1, 2, 3, 4, 5]
incremented_numbers = numbers.map { |n| n + 1 }
incremented_numbers
Wynik
=> [2, 3, 4, 5, 6]
A co stanie się ze zmienną numbers? Nic, ona pozostaje niezmieniona.
Jeszcze jeden przykład:
words = ["hello", "world", "ruby"]
new_words = words.map { |word| word.upcase }
new_words
=> ["HELLO", "WORLD", "RUBY"]
words
=> ["hello", "world", "ruby"]
Metoda upcase modyfikuje litery (zmienia je na wielkie). Zatem zmienna new_words zawiera zmodyfikowane słowa, a words pozostaje niezmieniona.
Przy okazji, w tych przykładach używamy konstrukcji bloku w klamrach. Blok można również przekazywać za pomocą do ... end (w przypadkach, gdy kod jest zbyt długi i dobrze byłoby go podzielić na kilka linii). To znaczy:
numbers.map { |n| n + 1 }
to to samo co
numbers.map do |n|
n + 1
end
No i przykład z przekazywaniem wyniku do zmiennej:
incremented_numbers_braces = numbers.map { |n| n + 1 }
incremented_numbers_do_end = numbers.map do |n|
n + 1
end
Jeszcze jeden przykład, ale będziemy modyfikować hash
hash = { a: 1, b: 2, c: 3 }
incremented_hash = hash.map { |key, value| [key, value + 1] }
incremented_hash
=> [[:a, 2], [:b, 3], [:c, 4]]
Ale jest pewien szczegół. Wykonanie map zwraca nam Array (tablicę). Zatem musimy przekonwertować Array na Hash (za pomocą metody .to_h).
incremented_hash = incremented_hash.to_h
incremented_hash
=> {:a=>2, :b=>3, :c=>4}
Myślę, że w konstrukcji hash.map { |key, value| [key, value + 1] } jest dość jasne, że bierzemy key i value z każdego elementu hasha i zwracamy taką konstrukcję [key, value + 1]. To znaczy, wynikiem wykonania map dla elementu będzie zwrócenie tablicy, gdzie pierwszy element to key, a drugi to zmodyfikowane value (value + 1).Wynik wykonania na całej kolekcji jest taki:
incremented_hash => [[:a, 2], [:b, 3], [:c, 4]]
Tablica tablic. Które później konwertujemy na hash (wywołanie to_h).
map! - modyfikuje oryginalną tablicę
Wykrzyknik dodany do metody map oznacza, że oryginalna kolekcja (zmienna) zostanie zmodyfikowana. Tego typu wywołania metody należy używać ostrożnie.
numbers = [1, 2, 3, 4, 5]
numbers.map! { |n| n + 1 }
numbers
=> [2, 3, 4, 5, 6]
- map: Tworzy nową tablicę, pozostawiając oryginalną tablicę niezmienioną.
- map!: Modyfikuje oryginalną tablicę, zmieniając jej elementy na miejscu.
Dlaczego taka nazwa metody (map)?
Nazwa map pochodzi od matematycznej operacji "odzwierciedlenia" (mapping), gdzie każdy element jednego zbioru "odzwierciedla się" w odpowiednim elemencie drugiego zbioru. W programowaniu oznacza to zastosowanie funkcji lub bloku kodu do każdego elementu kolekcji, aby stworzyć nową kolekcję z wynikami tych zastosowań.
Metoda map w Ruby jest potężnym narzędziem do przetwarzania kolekcji, które pozwala łatwo tworzyć nowe kolekcje, przekształcając każdy element za pomocą zadanego bloku. Ma dodatkowe możliwości (np. użycie indeksów), alternatywy (np. each) i nawet synonimy (collect). Ale celem tego wpisu było wyjaśnienie zasady działania metody map bez zbędnych komplikacji. Inne rzeczy omówimy w następnych wpisach o Ruby.
Ten post nie ma jeszcze żadnych dodatków od autora.