Dada
|> Structures
|> Algorithms

Looping in Ruby

How to get a for loop in Ruby

Looping in Ruby is usually a delight.

animals.each do |beast|
  beast.roar
end

Sometimes you need the index. So you call in #each_with_index

animals.each_with_index do |beast, index|
  puts "#{beast} #{index} says: #{beast.roar} "
end

If you feel functional, then you can use one of the Enumerable methods.

animals.map do |beast|
  beast.roar
end

For 90% of your looping needs, #each, or an Enumerable, #map, #select, #any?, #all?, etc, will do.

If you are working with a queue or a stack, you can always use the classic where loop

where !stack.empty?
  ghost = stack.pop
  pacman.chomp(ghost)
end

Yet every so often you will get to some problem where a classic for loop would be perfect. This is where it becomes awkward. Ruby doesn't have a classic for loop.

There is a for loop. But it is not C style for loop. Instead it loops over a collection. Usually a list or a range.

This is how it works. This will go by each element.

for i in list do
  puts i
end

In effect, it is a wordy version of #each. Therefore most people use #each.

But we want a C style for! Because sometimes using indices is the right solution to a problem. Even though we don't have something just like it, we can build something close to it.

Let's say you want something like this from C#

  for (var i = 0; i < list.Count; i++){
      console.WriteLn(list[i].ToString());
  }

You can replicate it by doing something like this

  for i in (0...list.length) do 
     puts list[i]
  end

Here we are using a range. So we will cycle through 0 to list.length - 1. We get that -1 automatically by using the ... range operator that says that we don't want to include the last number. If you wanted to include the last number, we would have written (0..list.length), but this would throw and out of range error when it got to the last item.

But what do you do when you want to go backwards? We can come up with something as well.

for i in (0...list.length).to_a.reverse do
  puts list[i]
end

Here we start with the range. We turn it into an array, and then we call reverse. Wordy? Yes. Does it get the job done? Also yes.

The good news is that these are rare scenarios.