Looping Backwards in Ruby

It so happens in Ruby that looping forwards is trivial; if you want to print out numbers from one to five, you can do so like this:


(1..5).each do |i|
puts i
end

This will print:

1
2
3
4
5

But how about going backwards? Can you do this?


(5..1).each do |i|
puts i
end

No! This won’t print anything out! Boo!

Edit: The solution is, happily, as easy as:

5.downto(1).do |i|
puts i
end

Props out to Wayne Conrad for mentioning it in the comments! In any case, you can read on to see a discussion of some other solutions to this problem–solutions that will work if you don’t know if you’re going to be counting up or counting down.


Ok, so you might do this, instead:


count = 5
while count > 0
puts count
count -= 1
end

Ok, that’ll work. But what if you have two variables, x and y, and you want to iterate from x and y–except you never know if x is less than y or greater than y? (If x is less than y, you can use the usual (x..y).each do |i|, but if not, what then?)

There are a couple of ways you can tackle this–one is swapping, and the other is using min/max, and we discuss the reverse series method.

Swapping means swapping x and y if x > y, like so:


x = #...
y = #...

if (x > y)
temp = x
x = y
y = temp
end

(x..y).each do #...

This is a great solution. Sometimes, though, it doesn’t work–like in my case, I had an issue where I go from x to y, and then from y to some other value. Swapping just destroys the second part of the process.

Which brings us to solution two–using min/max functions (which, incidentally, don’t come built-in to Ruby). So you would write:


(min(x, y)..max(x, y)).each do #...

And this will iterate properly, without destroying the values of x and y. Of course, you can define min/max as:


def min(a, b)
return b unless a < b
return a
end


def max(a, b)
return b unless a > b
return a
end

And you can use this solution. AND, if you don't know if x is greater than or less than y, then this solution will STILL work! Yay!

BUT! this solution still iterates forward! If that's a problem, you can try solution three, the reverse series. Observe:


steps = y - x
while (steps > 0)
i = y - steps #(y, y-1, y-2 ... x)
# do something for step i
end

This iterates backwards; the value of i is y, then y-1, then y-2, and so on, up to x. (Or, as mentioned before, you can use downto.)

Phew! So that covers a few different ways of iterating backwards; use whatever works for your needs.

Source : http://www.railsrocket.com/looping-backwards-in-ruby