Iterators are methods tied to a block(created using do and end) which executes statements multiple times, just like a loop. In Ruby iterators are frequently used instead of while and for loops.
Syntax:
object.iterator do
# block tied to iterator
statements
end
If there is only one statement inside a block then you can also write above syntax as:
object.iterator { statement }
Here block is enclosed using curly braces {} and iterator method and block must be on the same line. So you can't do this:
object.iterator # ERROR
{ statement }
Ruby comes with many built-in iterators, in this lesson we will focus on built-in iterators later we will learn how to create our own iterator methods.
times iterator
times allows you to execute statements inside a block certain number of times. Here is how to use times iterator.
Create a new file p_20_1.rb with the following code.
#p_20_1.rb
=begin
Program to demonstrate times iterator.
This code will generate 10 random numbers
=end
10.times do
puts rand(10)
end
Expected Output:
C:learn ruby>ruby p_20_1.rb
2
1
3
9
2
4
6
2
1
7
C:learn ruby>
If there is only one statement inside a block, then you can put statement in the same line as iterator method.
#p_20_2.rb
=begin
Program to demonstrate times iterator.
This code will generate 10 random numbers
=end
10.times { puts rand(10) }
Expected Output:
C:learn ruby>ruby p_20_2.rb
6
7
2
6
2
1
5
9
6
0
C:learn ruby>
Normally iterators return a value in each iteration, we need to write variable name within pipe character ( | ) as the first thing inside a block. Let's access this value
#p_20_3.rb
=begin
times iterator returns a number from 0 to 1
less than total iteration made by the iterator
=end
10.times { |i| puts i }
Expected Output:
C:\learn ruby>ruby p_20_3.rb
0
1
2
3
4
5
6
7
8
9
C:\learn ruby>
upto iterator
upto iterator: It goes from x to y , where y must be greater than x .
#p_20_4.rb
=begin
upto iterator returns a number between x and y.
It starts with x and ends at y.
In the first iteration it returns 1.
And in the last iteration it returns 10
=end
1.upto(10) { |i| puts i }
Expected Output:
C:\learn ruby>ruby p_20_4.rb
1
2
3
4
5
6
7
8
9
10
C:\learn ruby>
downto iterator
downto iterator: It goes from x to y , where x must be greater than y .
#p_20_5.rb
=begin
downto iterator returns a number between x and y.
It starts with x and ends at y.
In the first iteration it returns 10.
And in the last iteration it returns 11
=end
10.downto(1) { |i| puts i }
Expected Output:
C:\learn ruby>ruby p_20_5.rb
10
9
8
7
6
5
4
3
2
1
C:\learn ruby>
step iterator
step iterator allows you to specify start position, end position and step size. It only works with array and range. step iterator when used with array accepts two arguments: the upper limit and step size. When used with range it accepts only one argument step size.
#p_20_6.rb
=begin
This program prints uses step iterator to
print only even numbers
=end
puts "step iterator with array"
10.step(20, 2) { |i| puts i }
puts "step iterator with range"
(10..20).step(2) { |i| puts i }
Expected Output:
C:\learn ruby>ruby p_20_6.rb
step iterator with array
10
12
14
16
18
20
step iterator with range
10
12
14
16
18
20
C:\learn ruby>
Iterating through collections
each iterator is the most commonly used iterator to iterate through the elements of an array, range and hashes.
Create a new file p_20_7.rb with the following code.
#p_20_7.rb
=begin
This program uses each iterator to
access elements of an array, range and hash
=end
arr = [11,44,66,99]
puts "Iterating through array"
arr.each { |i| puts i }
###########
r = 40..50
puts "\nIterating through range"
r.each { |i| puts i }
##############
h = {
'key1'=> 'val1',
'key2'=> 'val2',
'key3'=> 'val3',
}
puts "\nIterating through hash"
# hash consist of two values key and value, so we will need two variables inside the block
h.each { |k, v| puts "#{k} : #{v}" }
Expected Output:
C:\learn ruby>ruby p_20_7.rb
11
44
66
99
C:\learn ruby>
map iterator
map iterator steps through elements of an array, range or hash and in the process creates a new array based on the values returned by the block.
Create a new file p_20_8.rb with the following code.
#p_20_8.rb
=begin
This program uses map iterator to
create a new array from the elements of array, range and hash
=end
# map iterator with array
arr = [65,89,21,98]
new_arr = arr.map { |i| i * 2 }
puts "old array " + arr.inspect
puts "new array " + new_arr.inspect
puts
################
# map iterator with range
r = 20..30
new_r = r.map { |i| i * 3 }
puts "range " + r.inspect
puts "array created from range " + new_r.inspect
puts
################
# map iterator with hash
h = {
'key1'=> 'val1',
'key2'=> 'val2',
'key3'=> 'val3',
}
new_h = h.map { |k, v| "#{k} : #{v}" }
puts "hash " + r.inspect
puts "array created from hash " + new_h.inspect
Expected Output:
C:\learn ruby>ruby p_20_8.rb
old array [65, 89, 21, 98]
new array [130, 178, 42, 196]
range 20..30
array created from range [60, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90]
hash 20..30
array created from hash ["key1 : val1", "key2 : val2", "key3 : val3"]
C:\learn ruby>
If you want to permanently alter the original array use map! (remember that methods whose names end with exclamation point (! ) permanently alters the object to which they are applied)
each_pair iterator
We have already learnt that each iterator can be used with hashes, but Ruby provides a more efficient way to iterate through hashes using each_pair iterator.
#p_20_9.rb
=begin
This program uses each_pair iterator to
access elements of a hash
=end
h = {
'key1'=> 'val1',
'key2'=> 'val2',
'key3'=> 'val3',
}
h.each_pair { |k, v| puts "#{k} : #{v}" }
Expected Output:
C:\learn ruby>ruby p_20_9.rb
key1 : val1
key2 : val2
key3 : val3
C:\learn ruby>
select iterator
select iterator returns an array of values for which code block returns true. It can be used with array, range and hash
#p_20_10.rb
=begin
This program demonstrate the use of select iterator
=end
arr = [34, 98, 56, 100, 89, 37, 11, 52]
new_arr = arr.select { |i| i % 2 == 0 }
puts new_arr.inspect
Expected Output:
C:\learn ruby>ruby p_20_10.rb
[34, 98, 56, 100, 52]
C:\learn ruby>
count iterator
count iterator is used to count elements for which code blocks returns true. It can be used with array, range and hash
#p_20_11.rb
=begin
This program demonstrate the use of count iterator
=end
arr = [34, 98, 56, 100, 89, 37, 11, 52]
n = arr.count { |i| i % 2 == 0 }
puts n
Expected Output:
C:\learn ruby>ruby p_20_11.rb
5
C:\learn ruby>
delete_if iterator
delete_if iterator deletes elements from an array for which code blocks returns true.
#p_20_12.rb
=begin
Following program demonstrate use of delete_if iterator.
=end
arr = [34, 98, 56, 100, 89, 37, 11, 52]
arr.delete_if { |i| i % 2 == 0 }
puts arr.inspect
Expected Output:
C:\learn ruby>ruby p_20_11.rb
[89, 37, 11]
C:\learn ruby>
This article was originally appeared at http://ruby.codeindepth.com/iterators-in-ruby/