Domness
Domness

Reputation: 7605

Sorting a hash of hashes

I have a hash that contains a number of keys/values that need sorting by their deepest value.

Here is an example of what I am dealing with:

hash = {"en"=> 
    { "key1"=> 
        {"foo1"=>1, 
         "foo2"=>2, 
         "foo3"=>1}, 
      "key2"=>
        {"foo4"=>1,
         "foo5"=>3, 
         "foo6"=>2, 
         "foo7"=>1}
    }
 "fr"=>
    ....
}

I want to key each main key (i.e. "en", "fr", es") and sort by the values for the keys within. So having "en" and for "key1" to have "value2" at the top with the highest number (frequency). Then doing the same for the rest of the hash. I'm not bothered about the order of the keys "en", "fr" etc.

So I want the output to be something like this:

hash = {"en"=> 
    { "key1"=> 
        {"foo2"=>2, 
         "foo1"=>1, 
         "foo3"=>1}, 
      "key2"=>
        {"foo5"=>3,
         "foo6"=>2, 
         "foo4"=>1, 
         "foo7"=>1}
    }
 "fr"=>
    ....
}

Upvotes: 2

Views: 165

Answers (1)

Phrogz
Phrogz

Reputation: 303520

Fragile, but should work:

def sort_deep(h)
  if h.values.all?{ |o| o.is_a? Numeric }
    Hash[ h.sort_by{|k,v|[-v,k]} ]
  else
    Hash[ h.map{ |k,v| [ k, sort_deep(v) ] } ]
  end
end

Proof:

hash = {"en"=> 
    { "key1"=> 
        {"foo1"=>1, 
         "foo2"=>2, 
         "foo3"=>1}, 
      "key2"=>
        {"foo4"=>1,
         "foo5"=>3, 
         "foo6"=>2, 
         "foo7"=>1}
    },
 "fr"=>
    { "key1"=> 
        {"foo1"=>91, 
         "foo2"=>22, 
         "foo3"=>12}, 
      "key2"=>
        {"foo4"=>21,
         "foo5"=>31, 
         "foo6"=>27, 
         "foo7"=>11}
    }
}
require 'pp'
pp sort_deep(hash)
#=> {"en"=>
#=>   {"key1"=>{"foo2"=>2, "foo1"=>1, "foo3"=>1},
#=>    "key2"=>{"foo5"=>3, "foo6"=>2, "foo4"=>1, "foo7"=>1}},
#=>  "fr"=>
#=>   {"key1"=>{"foo1"=>91, "foo2"=>22, "foo3"=>12},
#=>    "key2"=>{"foo5"=>31, "foo6"=>27, "foo4"=>21, "foo7"=>11}}}

Upvotes: 2

Related Questions