How would I reverse the elements in the hash, keeping the same values and keys, but reversing their order in the hash.
Like so:
{ \"4\" => \"happiness
In Ruby 1.8.7, the order of elements in a hash is documented to be not under our control, so none of the above methods work. In Ruby 1.9.3, things work and are documented in the way that the other answers rely upon.
$ irb1.8 h = { "4" => "happiness", "10" => "cool", "lala" => "54", "1" => "spider" } Hash[h.to_a().reverse()] => {"lala"=>"54", "1"=>"spider", "10"=>"cool", "4"=>"happiness"} quit $ irb1.9.1 h = { "4" => "happiness", "10" => "cool", "lala" => "54", "1" => "spider" } Hash[h.to_a().reverse()] =>{"1"=>"spider", "lala"=>"54", "10"=>"cool", "4"=>"happiness"}
The Ruby 1.8.7 way was ingrained so firmly for me that I misunderstood the question for quite some time. I thought it requested a way to Hash#invert: ie to transform the hash such that the range maps to the domain. That method discards duplicates. Luís Ramalho proffers a method that doesn't, but it's a bit clunky. This is a little shorter:
$ irb def invertWithDuplicates(original) inverse = Hash.new() { |hash, key| hash[key] = []; } original.each_pair() { |key, value| inverse[value].push(key); } return inverse end h = { "4" => "happiness", "10" => "cool", "lala" => "54", "1" => "cool" } invertWithDuplicates(h) => {"happiness"=>["4"], "cool"=>["1", "10"], "54"=>["lala"]}
Sorry to drift away from the OP's intended topic, though I submit that this does fit the post's title "Reverse a hash in Ruby".