loop
to pętla nieskończona. Należy jej używać ostrożnie:
loop do
puts "Pętla nieskończona"
sleep(1)
end
(Możesz ją przerwać klikając na czarny kwadrat powyżej.)
Zwykle jest wykorzystywana w połączeniu z poleceniem break
, które powoduje jej przerwanie:
loop_count = 0
loop do
loop_count += 1
puts "Pętla skończona #{loop_count}"
break if loop_count >= 10
end
Jeśli jednak isnieje tylko jeden warunek opuszczenia pętli, zwykle korzystamy z pętli while
lub until
.
Pierwsza z nich wykonuje się, tak długo jak warunek jest spełniony, np.
counter = 1
while(counter < 10) do
puts "Pętla until #{counter}"
counter += 1
end
Pętla until
wykonuje się zaś do momentu, w którym warunek zostanie spełniony:
counter = 1
until(counter > 10) do
puts "Pętla until #{counter}"
counter += 1
end
Można jej użyć, np. do wyświetlenia zawartości pliku:
file = File.open("data/books.csv")
until(file.eof?) do
puts file.readline.chomp
end
W Ruby nie ma klasycznej pętli for
znanej z języka C, tzn. for(i = 0; i < 10; i++)
. Istnieje jednak pętla for
, która służy do iterowania po strukturach sekwencyjnych, np. tablicach:
letters = ["a","b","c"]
for letter in letters do
puts letter
end
Można jej również użyć do innych struktur, np. tablic asocjacyjnych:
letters = {1 => "a", 2 => "b", 3 => "c"}
for index,letter in letters do
puts "#{index}. #{letter}"
end
Chociaż w Ruby nie ma klasycznej pętli for
to istnieją inne konstrukcje, pozwalające na wykonanie pętli określoną ilość razy.
Pierwszą z nich jest times
- jej semantyka jest bardzo prosta. Ponieważ wywoływana jest dla liczb naturalnych, kod wykonuje się tyle razy, ile wynosi wartość danej liczby:
3.times do
puts "Witaj EPI!"
end
upto
i downto
mają podobne zastosowanie. upto
pozwala na określenie dolnego i górnego zakresu:
10.upto(20) do |index|
puts "Indeks wynosi #{index}"
end
downto
również pozwala na określenie zakresu, ale wykonywana jest od wartości największej, do najmniejszej:
20.downto(10) do |index|
puts "Indeks wynosi #{index}"
end
step
pozwala na swobodne określenie kroku:
10.step(20,2) do |index|
puts "Indeks wynosi #{index}"
end
Wiedząc, że w w 2016 roku pierwsza niedziela wypada 3 stycznia, określ numery pozostałych dni, w które wypada niedziela. Nie chodzio daty, tylko numery dni w roku (3, 10, itd.)
Metody iteracyjne pozwalają wykonywać operacje na elementach kontenerów. Są one odpowiednikami pętli w innych językach programowania. Pozwalają jedak bardziej bezpośrednio wyrazić jaka jest intencja twórcy algorytmu.
Najczęściej używaną metodą iteracyjną jest each
, która wywołuje blok kodu dla każdego elementu tablicy
[1,2,3,4].each do |element|
puts element ** 2
end
Dzięki metodzie each
możemy uzyskać ten sam efekt jaki daje metoda upto
, jeśli wywołamy ją na zakresie:
1.upto(10){|i| puts "upto: #{i}" }
(1..10).each{|i| puts "each: #{i}" }
Ruby definiuje jednak znacznie więcej przydatnych metod tego rodzaju. Często używaną jest select
, która wybiera z tablicy tylko
te elementy, dla których blok kodu zwrócił wartość true
[1,2,3,4,5,6].select{|e| e % 2 == 0 }
["Ala", "Anna", "Agata", "Barbara"].select{|imie| imie =~ /^A/ }
Metoda ta ma komplementarną wobec niej metodę reject
[1,2,3,4,5,6].reject{|e| e % 2 == 0 }
["Ala", "Anna", "Agata", "Barbara"].reject{|imie| imie =~ /^A/ }
Bardzo często wykorzystywaną metodą jest również map
[1,2,3,4,5].map{|e| e * 2 }
["Ala", "Anna", "Agata"].map{|e| e.upcase }
Nieco rzadziej wykorzystywaną metodą jest inject
, która poza tym, że przechodzi przez wszystkie elementy, przekazuje do bloku
wynik eweluacji wcześniejszego wyrażenia. Pozwala to w bardzo prosty sposób np. oblicyć sumę elementów tablic
[1,2,3,4].inject(0){|suma,element| suma + element }
Oczywiście metoda ta nie działa wyłącznie na liczbach. Można np. skonkatenować jakiś napis
["Ala", "Anna", "Agata"].inject(""){|wynik,imie| wynik + " #{imie.upcase}" }
Na koniec warto wspomnieć o dwóch metodach służących do sortowania: sort
oraz sort_by
. Wywołanie tej pierwszej
bez bloku kodu spowoduje posortowanie elementów w naturany sposób
[3,1,7,6,2].sort
Możemy jednak zdefiniować swój własny sposób sortowania. Konieczne jest wtedy przekazanie bloku kodu, który akceptuje dwa argumentu podlegające porównaniu, np.
["A","całego","małe","Ala","Be"].sort{|a,b| a.size <=> b.size }
Warto porównać wynik tej metody z metodą sort
bez bloku:
["A","całego","małe","Ala","Be"].sort
Metoda sort_by
pozwala natomiast posortować elementy względem wybranej własności. Sortowanie względem długości łańcuchów można
zrealizować następująco:
["A","całego","małe","Ala","Be"].sort_by{|a| a.size }
Napisz program, który oblicza sumę cyfr zadanej liczby.
liczba = 1456323465
Napisz program, który wśród liczb od 0 do 100 znajduje wszystkie liczby które są podzielne przez 2, ale nie są podzielne przez 4 i których suma cyfr jest podzielna przez 7.
Załóżmy, że w turnieju szachowym jest 6 zawodników: Anna, Beata, Andrzej, Wojtek, Jan i Klaudia. Napisz kod, który znajdzie wszystkie możliwe mecze rozgrywane przez zawodników. Mecze rozgrywane pomiędzy tymi samymi zawodnikami nie mogą się powtarzać (kolejność zawodników nie ma znaczenia).