133

I'm probably missing something obvious, but is there a way to access the index/count of the iteration inside a hash each loop?

hash = {'three' => 'one', 'four' => 'two', 'one' => 'three'}
hash.each { |key, value| 
    # any way to know which iteration this is
    #   (without having to create a count variable)?
}
Andrew Grimm
  • 78,473
  • 57
  • 200
  • 338
Upgradingdave
  • 12,916
  • 10
  • 62
  • 72
  • 3
    Anon: No, hashes are not sorted. – Mikael S Jan 18 '10 at 02:31
  • hashes are not technically sorted, but in ruby you can sort them in a sense. sort() will convert them to a sorted nested array, which you can then convert back to a hash: your_hash.sort.to_h – jlesse Apr 03 '18 at 22:15

2 Answers2

331

If you like to know Index of each iteration you could use .each_with_index

hash.each_with_index { |(key,value),index| ... }
Michael Shimmins
  • 19,961
  • 7
  • 57
  • 90
YOU
  • 120,166
  • 34
  • 186
  • 219
  • 26
    specifically: `hash.each_with_index { |(key,value),index| ... }` – rampion Jan 18 '10 at 02:42
  • 23
    the parens are necessary b/c `hash.each` gives each key-value pair in an `Array`. The parens do the same thing as `(key,value) = arr`, putting the first value (the key) into `key`, and the second into `value`. – rampion Jan 18 '10 at 02:45
  • 1
    Thanks @S.Mark, @rampion, that worked. I didn't see `each_with_index` listed in the RDoc for Hash: http://ruby-doc.org/core/classes/Hash.html. Now I see that it's a member of Enumerable. But too bad that RDoc can't cross reference `each_with_index` from Hash.html. – Upgradingdave Jan 18 '10 at 02:50
  • 2
    @Dave_Paroulek I've often wished the same. I've found checking the parent modules manually a necessary step when using vi to check a classes's methods. Often I just skip to `irb`, and use `ClassName#instance_methods` to make sure there's nothing I missed. – rampion Jan 20 '10 at 20:27
  • Thx, @rampion, `ClassName#instance_methods` has been very helpful – Upgradingdave Jan 25 '10 at 01:41
15

You could iterate over the keys, and get the values out manually:

hash.keys.each_with_index do |key, index|
   value = hash[key]
   print "key: #{key}, value: #{value}, index: #{index}\n"
   # use key, value and index as desired
end

EDIT: per rampion's comment, I also just learned you can get both the key and value as a tuple if you iterate over hash:

hash.each_with_index do |(key, value), index|
   print "key: #{key}, value: #{value}, index: #{index}\n"
   # use key, value and index as desired
end
Kaleb Brasee
  • 51,193
  • 8
  • 108
  • 113
  • Downvoted for accessing the iterated collection from inside the loop and an erroneous code: `key` in the first loop is an array of key+value pair, so using it as an index in `hash` is wrong. Have you ever tested it? – SasQ Aug 23 '13 at 05:28