Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the .each iterator in ruby guaranteed to give the same order on the same elements every time?

I'm doing something like this with a list 'a':

a.each_with_index |outer, i|
  a.each_with_index |inner, j|
    if(j > i)
      # do some operation with outer and inner
    end
  end
end

if the iterator is not going to use the same order, this won't work. I don't care what the order actually is, I just need for two .each_with_index iterators to use the same order.

I would assume that it would be a property of an array that it has a fixed order and I'm just being paranoid that the iterator wouldn't use that order...

like image 349
Jonathan Adelson Avatar asked Jul 05 '11 23:07

Jonathan Adelson


4 Answers

This depends on the specific Enumerable object you are operating on.

Arrays for example will always return elements in the same order. But other enumerable objects are not guaranteed to behave this way. A good example of this is the 1.8,7 base Hash. That is why many frameworks (most notably ActiveSupport) implement an OrderedHash.

One interesting side note: Even Hash will return objects in the same order if the hash has not changed between each calls. While many objects behave this way, relying on this subtlety is probably not a great idea.

So, no. The generic each will not always return objects in the same order.

P.S. Ruby 1.9's hashes are now actually ordered http://www.igvita.com/2009/02/04/ruby-19-internals-ordered-hash

like image 133
diedthreetimes Avatar answered Oct 18 '22 21:10

diedthreetimes


I've not looked at your actual code but here is your answer taken from the Ruby API docs:

Arrays are ordered, integer-indexed collections of any object.

So yes, you are being paranoid but surely that's a good thing when you're developing?

like image 44
Paul.s Avatar answered Oct 18 '22 20:10

Paul.s


Array by definition is an ordered list of elements. So you should have no problems with that.

like image 2
Dmytrii Nagirniak Avatar answered Oct 18 '22 20:10

Dmytrii Nagirniak


It depends on the specific Enumerable. Certainly an Array will always iterate in the obvious order.

It would be quite lunatic fringe for someone to implement an each method that would traverse the same collection in different ways, but the only actual restriction for such a "feature" would be in the documentation for the class that mixes in Enumerable. Well, in that and the sanity of the implementors.

I can almost imagine some sort of cryptographic API that deliberately traversed a collection in an unpredictable way.

like image 1
DigitalRoss Avatar answered Oct 18 '22 19:10

DigitalRoss