Cała oryginalna treść jest tworzona po ukraińsku. Nie wszystkie treści zostały jeszcze przetłumaczone. Niektóre posty mogą być dostępne tylko po ukraińsku.Dowiedz się więcej

Jak działają tablice w Ruby: praktyczne przykłady each, map, select, inject, reduce, filter_map

Okładka posta: Jak działają tablice w Ruby: praktyczne przykłady each, map, select, inject, reduce, filter_map
Ta treść została automatycznie przetłumaczona z ukraińskiego.
Tablice to jedna z najwygodniejszych struktur danych w Ruby. Są elastyczne, dynamiczne i mają ogromną liczbę wbudowanych metod, które pozwalają na eleganckie przetwarzanie danych. Przyjrzyjmy się głównym z nich na przykładach.

each - prosty przebieg elementów

Metoda each iteruje tablicę i wykonuje blok kodu dla każdego elementu. Zwykle używa się jej, gdy trzeba coś zrobić z elementami, ale nie tworzyć nowej tablicy.
[1, 2, 3, 4, 5].each do |n|
  puts "Liczba: #{n}"
end
Wynik:
Liczba: 1
Liczba: 2
Liczba: 3
Liczba: 4
Liczba: 5
=> [1, 2, 3, 4, 5]
each zawsze zwraca oryginalną tablicę, a nie wynik wykonania bloku. Co to oznacza? Blok wykonuje puts (widzisz wydrukowane "Liczba 1" i tak dalej). A iterator zwraca tablicę => [1, 2, 3, 4, 5]
Oznacza to, że jeśli przekażemy wartość iteratora do zmiennej - otrzymamy tablicę.
myvar = [1, 2, 3, 4, 5].each do |n|
  puts "Liczba: #{n}"
end

Liczba: 1
Liczba: 2
Liczba: 3
Liczba: 4
Liczba: 5
=> [1, 2, 3, 4, 5]

myvar
=> [1, 2, 3, 4, 5]

map - transformacja elementów

Metoda map (lub collect) tworzy nową tablicę, w której każdy element to wynik wykonania bloku.
numbers = [1, 2, 3, 4, 5]
squares = numbers.map { |n| n ** 2 }

p squares  # => [1, 4, 9, 16, 25]
Używaj map, gdy potrzebujesz uzyskać nowy zestaw danych z istniejącej tablicy.
Jakie są różnice między map a collect?
W Ruby map jest po prostu bardziej znaną nazwą dla programistów, którzy przyszli z innych języków (JavaScript, Python itd.). A collect to historyczna nazwa, która pozostała z wczesnych wersji Ruby (pod wpływem Smalltalk).
Jeśli spojrzeć na kod Ruby (moduł Enumerable):
alias collect map
czyli to dokładny synonim, nie opakowanie, nie delegat - po prostu inna nazwa tej samej metody.

select - filtrowanie elementów

Metoda select zwraca tablicę elementów, dla których blok zwraca true.
numbers = [1, 2, 3, 4, 5]
even_numbers = numbers.select { |n| n.even? }

p even_numbers  # => [2, 4]
Istnieje metoda odwrotna - reject, która zwraca elementy, dla których blok zwraca false.
odd_numbers = numbers.reject { |n| n.even? }
p odd_numbers   # => [1, 3, 5]

inject / reduce - akumulacja wartości

inject (synonim reduce) to potężne narzędzie do "zwiń" tablicę w jedną wartość. Można policzyć sumę, zbudować hasz itd.
numbers = [1, 2, 3, 4, 5]

sum = numbers.inject(0) { |acc, n| acc + n }
p sum  # => 15
Przyjmuje wartość początkową (w naszym przypadku 0) i przekazuje ją razem z każdym elementem tablicy do bloku.
Składnia:
array.inject(initial_value) { |accumulator, element| ... }
  • accumulator - zmienna, w której przechowywany jest bieżący wynik.
  • element - bieżący element tablicy.
  • Blok zwraca nową wartość dla accumulator.
Jeszcze jeden przykład - połączenie elementów w ciąg (string):
words = ["Ruby", "jest", "fajne"]
sentence = words.reduce("") { |acc, word| acc + word + " " }
p sentence.strip  # => "Ruby jest fajne"
strip użyto, aby usunąć zbędną spację na końcu.
Budowa haszu będzie wyglądać tak:
letters = %w[a b c]
indexed = letters.inject({}) { |acc, l| acc[l] = l.upcase; acc }
# => {"a"=>"A", "b"=>"B", "c"=>"C"}
Jednak tutaj jest trochę trudniej. Metoda inject (lub reduce) przechodzi przez kolekcję i stopniowo akumuluje wynik w akumulatorze (acc).
Przekazujemy {} - czyli wartość początkową akumulatora - pusty hasz.
{ |acc, l| acc[l] = l.upcase; acc }
To blok, który jest wywoływany dla każdego elementu l w tablicy.
  • acc - to bieżący akumulator (na początku {})
  • l - bieżąca litera ("a", potem "b", potem "c")
Wewnątrz bloku:
acc[l] = l.upcase
dodaje do hasza parę:
  • klucz: l (na przykład "a")
  • wartość: l.upcase (czyli "A")
Po tym zwracamy sam acc, aby przekazać go do następnej iteracji
Oczywiście można to zrobić w inny sposób, ale tutaj rozważamy możliwości tych metod.

filter_map - magia Ruby 2.7+

Metoda filter_map łączy map i select w jednym przebiegu tablicy. Przekształca i filtrowa jednocześnie.
numbers = [1, 2, 3, 4, 5, 6]
even_squares = numbers.filter_map { |n| n**2 if n.even? }

p even_squares  # => [4, 16, 36]
To wygodniejsze i bardziej efektywne niż numbers.select { ... }.map { ... }.

Ten post nie ma jeszcze żadnych dodatków od autora.

Jak działa self, protected i private (Ruby)
28 paź 13:52

Jak działa self, protected i private (Ruby)

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
Dzielenie całkowite w Ruby: dlaczego 6 / 4 równa się 1
28 paź 14:10

Dzielenie całkowite w Ruby: dlaczego 6 / 4 równa się 1

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
28 paź 14:42

Jak działa &:to_s w Ruby i co to jest Symbol#to_proc

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
Co to jest Proc i Lambda w Ruby?
28 paź 15:57

Co to jest Proc i Lambda w Ruby?

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
Co się stanie, jeśli wywołasz [1, 2, 3].map(&Person)
29 paź 17:54

Co się stanie, jeśli wywołasz [1, 2, 3].map(&Person)

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
Klasa Singleton (eigenclass) w Ruby: co to jest i po co to potrzebne
29 paź 18:29

Klasa Singleton (eigenclass) w Ruby: co to jest i po co to potrzebne

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska