ruby-on-railsrubyruby-1.8

How to sort a hash by values


I was trying to sort a particular hash by values. I came across a way using the method sort_by. But even though I call sort_by on a hash, it returns an array, i.e.:

a = {}
a[0] = "c"
a[1] = "b"
a[2] = "a"
a.sort_by{|key, value| value}
# => [[2, "a"], [1, "b"], [0, "c"]]

If I try to convert the result into a hash, I end up with a hash sorted on key, hence the whole purpose of sort_by is lost. i.e.:

a = {}
a[0] = "c"
a[1] = "b"
a[2] = "a"
Hash[*a.sort_by{|key, value| value}.flatten]
# => {0=>"c", 1=>"b", 2=>"a"}

Is there a way I can sort a hash by value and yet get the results back in the form of a Hash?

I am using 1.8.6 ruby


Solution

  • You can use ActiveSupport::OrderedHash for Ruby 1.8:

    ActiveSupport::OrderedHash implements a hash that preserves insertion order, as in Ruby 1.9

    I don't have 1.8.6 running, but this should work:

    a = {}
    a[0] = "c"
    a[1] = "b"
    a[2] = "a"
    
    ordered = ActiveSupport::OrderedHash[*a.sort_by{|k,v| v}.flatten]
    ordered.keys
    # => [2, 1, 0], this order is guaranteed
    

    As noted in the quote above hashes in Ruby 1.9 "enumerate their values in the order that the corresponding keys were inserted", so this is only needed for Ruby 1.8.