Ruby Iterators
Iterators are nothing but methods supported by collections. Objects that store a group of data members are called collections. In Ruby, arrays and hashes can be termed collections.
Iterators return all the elements of a collection, one after the other. We will be discussing a few of Ruby iterators here. Let's look at these in detail.
Ruby each Iterator:
The simplest iterator method. All iterables (such as arrays and hashes) in Ruby will have an each method that will allow you to loop over the values in the iterable and do something with each one.
[1,2,3,4,5,6,7,8,9,10].each {|value| print "#{value} "}
This will produce following result:
1 2 3 4 5 6 7 8 9 10
The each iterator executes code for each element in collection.
ary = [1,2,3,4,5]
ary.each do |i|
puts i
end
This will produce following result:
1
2
3
4
5
You always use the each iterator with a block. It returns each value of the array, one by one, to the block. The value is stored in the variable i and then displayed on the screen.
Ruby each_index Iterator:
If you have an array and doesn't want to loop over every value but rather over every index, the each_index iterator does the job:
array = ['A','B','C','D','E','F','G','H','I','J']
array.each_index {|i| print "#{i}-"}
This will produce following result:
0-1-2-3-4-5-6-7-8-9-
Ruby collect Iterator:
The collect iterator returns all the elements of a collection.
The collect method need not always be associated with a block. The collect method returns the entire collection, regardless of whether it is an array or a hash.
a = [1,2,3,4,5]
b = Array.new
b = a.collect
c = {'a' => 1, 'b' => 2}
d = c.collect
puts b.inspect
puts d.inspect
This will produce following result:
[1, 2, 3, 4, 5]
[["a", 1], ["b", 2]]
NOTE: The collect method is not the right way to do copying between arrays. There is another method called a clone which should be used to copy one array into another array.
You normally use the collect method when you want to do something with each of the values to get the new array. For example, this code produces an array b containing 10 times each value in a.
a = [1,2,3,4,5]
b = a.collect{|x| 10*x}
puts b.inspect
This will produce following result:
[10, 20, 30, 40, 50]
Notice: collect has a commonly used alias: "map".
As many other iterators, it can be used to transform one collection into another.
puts ['Antony', 'Richard','Kathy','Kopf'].map{|x| x.length}.inspect
This will produce following result:
[6, 7, 5, 4]
Ruby loop Iterator:
The simplest version of it is the infinite loop:
loop {puts "HELLO"}
This will produce following result:
HELLO
HELLO
HELLO
HELLO
.
.
.
When using the loop iterator, we will need termination and control keywords, Ruby provides: break, next and redo.
i=0
loop do
i+=1
print "#{i} "
break if i==10
end
This will produce following result:
1 2 3 4 5 6 7 8 9 10
i=0
loop do
i+=1
next if i==3
print "#{i} "
break if i==10
end
This will produce following result:
1 2 4 5 6 7 8 9 10
You can also pass a parameter to both next and break, and it will become the value returned by the loop.
for i in 1..5
puts "How many do you need on day #{i} ?"
STDOUT.flush
nneed = gets.chomp.to_i
# next - don't order nothing; move on to next case
next(print 'nothing? ') if nneed == 0
# retry - whole thing to be redone on a 999 code
retry if [112,911,999].include?(nneed)
# redo - more than 10 ordered - must be a mistake
if nneed > 10 then
puts "Too many!"
redo
end
# break - code "-1" entered to exit on a short week
break(print 'stopped! ') if nneed == -1
puts "We'll get #{nneed} on order for day #{i}"
end
This may produce the following result:
How many do you need on day 1 ?
0
nothing? How many do you need on day 2 ?
911
How many do you need on day 1 ?
12
Too many!
How many do you need on day 1 ?
3
We'll get 3 on order for day 1
How many do you need on day 2 ?
4
We'll get 4 on order for day 2
How many do you need on day 3 ?
5
We'll get 5 on order for day 3
How many do you need on day 4 ?
-1
stopped!
Ruby times Iterator:
It is similar the classic for loop in other languages and will allow you to execute a loop and perform an action (according to the block you write) x number of times e.g.:
10.times {|i| print "#{i} "}
This will produce following result:
1 2 3 4 5 6 7 8 9
Ruby upto and step Iterators:
Once again it is similar to the classic for loop in that we execute from number x up to number y (y needs to be bigger than x obviously):
1.upto(10) {|i| print "#{i} "}
This will produce following result:
1 2 3 4 5 6 7 8 9 10
We can also use step to iterate while skipping over a range of numbers on every iteration:
1.step(10, 2) {|i| print "#{i} "}
This will produce following result:
1 3 5 7 9
Ruby has plenty more iterators where "each" came from. Which one should be used depends on what operation you are trying to perform...


