Przegląd 20 iteratorów w Rubim
Posted by Jacek Galanciak on May 19 2007
W dzisiejszym odcinku przyjrzymy się bliżej iteratorom w języku Ruby.
Do dzieła!
all?
Przekazuje do bloku każdy element kolekcji. Zwraca true
, jeśli blok nigdy nie zwróci false
(lub nil
)
[1, 2, 5].all? { |element| element <= 5 } # => true
[1, 2, 5].all? { |element| element <= 4 } # => false
%w{RAM CPU GPU DDR}.all? { |element| element.length == 3 } # => true
[1, 2, 5].all? do |element|
puts "Sprawdzam #{element}; #{element} < 5: #{element < 5}"
element < 5
end # => false
Wyjście:
Sprawdzam 1; 1 < 5: true
Sprawdzam 2; 2 < 5: true
Sprawdzam 5; 5 < 5: false
any?
Zwraca true
, jeśli przekazany do bloku element kiedykolwiek zwróci true
[1, 2, 5].any? { |element| element > 5 } # => false
[1, 2, 5].any? { |element| element == 2} # => true
collect (map)
Przekazuje do bloku każdy element kolekcji, następnie tworzy nową - z elementów zwracanych przez blok.
%w{kot tulipan parowka}.collect { |element| element.upcase }
# => ["KOT", "TULIPAN", "PAROWKA"]
[1, 2, 3].collect { |element| element + 1}
# => [2, 3, 4]
collect! (map!)
Działa jak collect
, z tą jednak różnicą, że operacji kolekcja dokonuje na sobie, w każdej iteracji zmieniając swoją zawartość.
a = [1, 2, 3] # => [1, 2, 3]
a.collect! { |element| element + 1 } # => [2, 3, 4]
a # => [2, 3, 4]
delete_if
Usuwa z kolekcji elementy, dla których blok zwraca true
[1, 2, 3, 4, 5, 6].delete_if { |i| i%2 == 0 } # => [1, 3, 5]
detect (find)
Zwraca pierwszy element, dla którego blok zwróci true
(36..100).detect { |i| i%7 == 0 } # => 42
downto
Wykonuje blok, podając w kolejności malejącej liczby od siebie samej do podanej jako parametr.
9.downto(0) { |i| print i }
9876543210
each
Przekazuje do bloku każdy z elementów kolekcji
['pies', 'kot', 'ryba'].each { |word| print word + " " } # => ["pies", "kot", "ryba"]
(0..9).each { |i| print i } # => (0..9)
# Wyjście: pies kot ryba 0123456789
each_index
Działa jak each
, ale przekazuje sam indeks każdego elementu.
[3, 6, -5].each_index { |i| print i.to_s + " " }
# Wyjście: 0 1 2
each_with_index
Przekazuje jednocześnie element i jego indeks do bloku.
["jeden", 2, "trzy"].each_with_index do |element, index|
puts "Indeksowi #{index} przyporządkowałem #{element}"
end
Indeksowi 0 przyporzdkowaem jeden
Indeksowi 1 przyporządkowałem 2
Indeksowi 2 przyporządkowałem trzy
find_all
Zwraca wszystkie elementy kolekcji, dla których blok zwróci true
(0..30).find_all { |i| i%9 == 0 } # => [0, 9, 18, 27]
grep
Zwraca elementy spełniające dopasowanie podane jako parametr. Jeśli podano blok, przekazuje do niego tylko te elementy i zwraca tablicę zbudowaną z wartości zwracanych przez blok.
# Zwraca wyrazy zawierające literę 'r'
%w{ruby python perl php}.grep(/r/) do |w|
print "#{w.upcase} "
w.capitalize
end # => ["Ruby", "Perl"]
RUBY PERL
inject
Przekazuje do bloku każdy element kolekcji. Posiada dodatkowo pamięć, która początkowo jest równa pierwszemu elementowi (lub wartości podanej jako parametr). Po zakończeniu każdej iteracji pamięć jest update'owana do wartości zwracanej przez blok.
# Zwraca największą liczbę z tablicy
a = [-5, 2, 10, 17, -50]
a.inject a.first do |mem, element|
mem > element ? mem : element
end # => 17
# Silnia
(1..5).inject do |mem, element|
mem *= element
end # => 120
partition
Zwraca dwie tablice: jedną z elementami, dla których blok zwraca true
, i drugą z resztą.
(1..6).partition { |i| i%2 == 0 } # => [[2, 4, 6], [1, 3, 5]]
reject
Odrzuca z kolekcji wszystkie elementy, dla których blok zwróci true
.
(1..10).reject { |i| i >= 3 and i <= 7 } # => [1, 2, 8, 9, 10]
reject!
Wyrzuca z siebie elementy, dla których blok zwraca true
a = (1..10).to_a # => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
a.reject! { |i| i >= 3 and i <= 7 } # => [1, 2, 8, 9, 10]
a # => [1, 2, 8, 9, 10]
reverse_each
Działa jak each
tyle, że podaje elementy w odwrotnej kolejności.
(0..9).to_a.reverse_each { |i| print i }
9876543210
step
Przekazuje do bloku wartości od, do - z określonym krokiem.
# (1)
0.step(100, 10) { |i| puts i}
# (2)
(0..100).step(10) { |i| puts i }
W obu przypadkach wyjście będzie wyglądało tak:
0
10
20
30
40
50
60
70
80
90
100
times
Wykonuje dany blok określoną ilość razy.
5.times { puts "Hej!" }
5.times { |i| print "#{i} "}
Hej!
Hej!
Hej!
Hej!
Hej!
0 1 2 3 4
upto
Iteruje blok, przekazując liczby od, do.
1.upto(3) { |i| print i }
123
Podsumowanie
Iteratory są bardzo ważną częścią języka, pozwalają wykonywać mniej lub bardziej skomplikowane czynności w sposób prosty i zwięzły. Warto w pełni poznać ich możliwości i, co ważne, korzystać z nich. Bo własnie to pokazuje, jak dobrzy jesteśmy w Rubim.