Iterators

Now we get to one of the coolest features of Ruby: iterators.

An iterator is a special kind of method. It is a method that lets you access items one at a time.

Arrays are not the only objects that have iterators, but the are one of the most important. Iterators are best seen through an example. Here we use Array#each:

friends = ["Melissa", "Jeff", "Ashley", "Rob"]  
friends.each do |friend|
  puts "I have a friend called " + friend 
end

This will produce:

I have a friend called Melissa  
I have a friend called Jeff
I have a friend called Ashley
I have a friend called Rob

The keen student might notice that this looks very similar to the first loop I showed you. The one with the form n.times do. This is, in fact, an iterator. And it lets you iterate over the integers from 0 to n-1:

4.times do |num|
  puts num
end

Which will produce:

0
1
2
3

The fact, that this starts counting at 0 might seem odd. But it actually matches arrays (which start counting at 0). Thus, the code:

friends = ["Melissa", "Jeff", "Ashley", "Rob"]  
friends.each do |friend|
  puts "I have a friend called " + friend 
end 

Can also be written as:

friends = ["Melissa", "Jeff", "Ashley", "Rob"]  
4.times do |i|
  puts "I have a friend called " + friends[i]  
end
(In most cases, you should never use single letter variables. In this case, “i” is the standard variable name for “index” and is universally understood.)

Now, here is something cool: remember the Array#length method? Using length, we can remove the literal “4”:

friends.length.times do |i|
  puts "I have a friend called " + friends[i]
end

Now suppose that I don’t want to print all my friends. I just want to print every other friend. We can just print out the friends that correspond to even numbered indices. We can do this with the remainder (Integer#%) method.

friends.length.times do |i|
  # print only even indices (i.e. remainder of i / 2 is 0).
  if  i % 2 == 0
    puts "I have a friend called " + friends[i]
  end
end

This produces:

I have a friend called Melissa  
I have a friend called Ashley

Now, say I want to print all my friends in alphabetical order:

friends.sort.each do |friend|
  puts "I have a friend called " + friend  
end

Which produces:

I have a friend called Ashley
I have a friend called Jeff
I have a friend called Melissa  
I have a friend called Rob

Exercises

  1. Print all the contents of friends in reverse alphabetical order.
  2. Say I have the array:
    bc. names = "daniel", "eduardo", "alejandro", "enrique"
    Use String#capitalize to print these names capitalized.

My very own library

 

I am confused about what ”|withastringinit|” does. I understand what #friends.each do |friend|# does in the first example but I don’t understand how it does it. How does ruby know what |friend| is?

 
 

How does “i % 2” work? I don’t understand what each element of this is doing.

 
 

how do you sort in the reverse order?

 
   

Scott: I think ruby creates a temporary variable with the given name and copies the value of the current array element into it. Some testing revealed that changes to the |friend| (could be called buddy, pal, chopped_liver) variable did not change the original data.

>> friends.each do |buddy|  buddy += 'meister' ; puts buddy  end
Biffmeister
Buffymeister
Xaviermeister
Zoemeister
Ahnoldmeister
=> ["Biff", "Buffy", "Xavier", "Zoe", "Ahnold"]
>> puts friends
Biff
Buffy
Xavier
Zoe
Ahnold
=> nil