Jeff
Jeff

Reputation: 4423

Rails - Sort Hash of Hashes based on subhash value

I have the following hash:

h = { "people"=>
        { "joe"   => { "score" => 3, "favorite_food" => "pizza"}, 
          "marry" => { "score" => 89, "favorite_food" => "ice_cream" }
         }
     }

How do I sort this hash based on score (and keep it sorted)?

ie: the result would be:

    { "people"=>
        { 
          "marry" => { "score" => 89, "favorite_food" => "ice_cream" }
          "joe"   => { "score" => 3, "favorite_food" => "pizza"}, 
         }
     }

Upvotes: 1

Views: 750

Answers (3)

Jeff
Jeff

Reputation: 4423

So, for completion, here is another way to sort it:

h.deep_symbolize_keys!
h[:people].sort_by {|k,v| v[:score]}.reverse!

I can't speak toward the efficiency of this, but it works.

Upvotes: 0

sebkkom
sebkkom

Reputation: 1446

If you prefer more self-explanatory (and longer) code, you can transform your hash of hashes (let's call it h) to an array of hashes (let's call it a) that contains all the elements you want to sort but slightly different and then perform the sorting on this array's elements - using whichever key you prefer:

a = []
p["people"].each do |p| 
  a << { :name => p, :score => p["score"], :food => p["food"] } 
end

sorted = a.sort_by { |e| e[:score] }

Upvotes: 1

Малъ Скрылевъ
Малъ Скрылевъ

Reputation: 16507

If you've meant the evaluation order of the hash values, then you have to reconstruct the sub-hash:

h[ 'people' ].replace(h[ 'people' ].to_a.sort do |x, y|
   y[1][ 'score' ] <=> x[1][ 'score' ]
end.to_h)

for older version of ruby, use Hash constructor:

h[ 'people' ].replace( Hash[h[ 'people' ].to_a.sort do |x, y|
   y[1][ 'score' ] <=> x[1][ 'score' ]
end] )

Additional note: the ordered hash is appeared from ruby version 2.1 (as far as I remember).

Upvotes: 1

Related Questions