Iterating in Ruby: 4 ways to go


The 4 different ways to iterate in Ruby


1. The Kernel#loop method


2. The control expressions


  • while..end
  • until..end
  • for..end

3. The Integer methods


  • Integer#times
  • Integer#upto
  • Integer#downto

4. The specific methods for collections


  • String#each_char
  • Array#each, Hash#each, Range#each
  • Enumerable#reverse_each, Array#reverse_each
  • Enumerable#each_with_index
  • Enumerable#each_with_object
  • Hash#each_pair, Hash#each_key, Hash#each_value

Remarks


The Kernel#loop method is the tank on the battlefield. It destroys everything on its way. You can always work your way to a working solution with this method, as long as you break properly.


When you use a control expression or the Kernel#loop method to iterate through the elements of a specific collection, you usually need to initialize a "counter" local variable. This local variable is needed to track the number of iterations executed, either by adding or substracting units.


The Integer methods are my favorite ones, because they do not need the initialization of a "counter" local variable. Also, I find them more natural to think with, especially when we have to build interdependent iterations. For example, to write a method that lists all substrings of a string, my favorite way to go is with the Integer#upto method.


Whatever option you choose to iterate with, you can modify how the iterations are executed by using Ruby's keywords: break, return, next.


The Enumerable methods are methods that are available to Enumerable collections. An Enumerable collection is a collection that has a #each method implemented in its Class. Enumerable methods can be used on Arrays, Hashes and Ranges.


I did not include the Enumerable#map in the previous list because it is an iterating and transforming method. If you just need to iterate through a collection without transforming its elements, there is no need to use the Enumerable#map method.


Examples


Let's consider the following exercise: given the array below, turn this array into a hash where the animals are the keys and the values are the positions in the array.


animals = ['Dog', 'Cat', 'Mouse', 'Flamingo']


With this exercise, we can use the 4 types of iterations. Let's go for a ride through 10 examples of code.


1. The Kernel#loop method


animals = ['Dog', 'Cat', 'Mouse', 'Flamingo']

hash = Hash.new
index = 0
max_index = animals.size - 1

loop do
  break if index >= max_index
  symbol = animals[index].to_sym
  hash[symbol] = index
  index += 1
end

p hash

2. Control expression: while..end


animals = ['Dog', 'Cat', 'Mouse', 'Flamingo']

hash = Hash.new
index = 0
max_index = animals.size - 1

while index <= max_index
  symbol = animals[index].to_sym
  hash[symbol] = index
  index += 1
end

p hash

3. Control expression: until..end


animals = ['Dog', 'Cat', 'Mouse', 'Flamingo']

hash = Hash.new
index = 0
max_index = animals.size - 1

until index > max_index
  symbol = animals[index].to_sym
  hash[symbol] = index
  index += 1
end

p hash

4. Control expression: for..end


animals = ['Dog', 'Cat', 'Mouse', 'Flamingo']

hash = Hash.new

for animal in animals
  symbol = animal.to_sym
  hash[symbol] = animals.index(animal)
end

p hash

5. Integer method: Integer#times


animals = ['Dog', 'Cat', 'Mouse', 'Flamingo']

hash = Hash.new
number_of_iterations = animals.size

number_of_iterations.times do |index|
  symbol = animals[index].to_sym
  hash[symbol] = index
end

p hash

Watch out for the number of iterations. In this case, It's not the maximum number of index, but the size of the array.


6. Integer method: Integer#upto


animals = ['Dog', 'Cat', 'Mouse', 'Flamingo']

hash = Hash.new
max_index = animals.size - 1

0.upto(max_index) do |index|
  symbol = animals[index].to_sym
  hash[symbol] = index
end

p hash

7. Integer method: Integer#downto (Not the natural way to go for this exercise)


animals = ['Dog', 'Cat', 'Mouse', 'Flamingo']

hash = Hash.new
max_index = animals.size - 1

max_index.downto(0) do |index|
  new_index = max_index - index
  symbol = animals[new_index].to_sym
  hash[symbol] = new_index
end

p hash

8. Specific method for collections: Array#each


animals = ['Dog', 'Cat', 'Mouse', 'Flamingo']

hash = Hash.new

animals.each do |animal|
  symbol = animal.to_sym
  hash[symbol] = animals.index(animal)
end

p hash

9. Specific method for collections: Enumerable#each_with_index


animals = ['Dog', 'Cat', 'Mouse', 'Flamingo']

hash = Hash.new

animals.each_with_index do |animal, index|
  symbol = animal.to_sym
  hash[symbol] = index
end

p hash

10. Specific method for collections: Enumerable#each_with_object


animals = ['Dog', 'Cat', 'Mouse', 'Flamingo']

hash = animals.each_with_object({}) do |animal, hash|
  symbol = animal.to_sym
  hash[symbol] = animals.index(animal)
end

p hash

Author:
Initial publication date:
Last updated: