Group Hash by values in ruby

Just Hash.select:

h1.select { |key, value| value == '0' } #=> {"users_milestones"=>"0", "users_goals"=>"0", ...}
h1.select { |key, value| value == '1' } #=> {"admin_milestones"=>"1", "admin_goals"=>"1", ...}

The return value depends on your Ruby version. Ruby 1.8 returns a array of arrays, whereas Ruby 1.9 returns a hash like in the example above.


You can group hash by its value:

h1 = {
  "admin_milestones"=>"1",
  "users_milestones"=>"0",
  "admin_goals"=>"1",
  "users_goals"=>"0", 
  "admin_tasks"=>"1", 
  "users_tasks"=>"0",
  "admin_messages"=>"1",
  "users_messages"=>"0",
  "admin_meetings"=>"1",
  "users_meetings"=>"0"
}

h2 = h1.group_by{|k,v| v}

It will produce a hash grouped by its values like this:

h2 = {"1"=>[["admin_milestones", "1"], ["admin_goals", "1"], ["admin_tasks", "1"], ["admin_messages", "1"], ["admin_meetings", "1"]], 
"0"=>[["users_milestones", "0"], ["users_goals", "0"], ["users_tasks", "0"], ["users_messages", "0"], ["users_meetings", "0"]]} 

If you want an array as answer the cleanest solution is the partition method.

zeros, ones = my_hash.partition{|key, val| val == '0'}

You should use group_by on the keys arrays and use the value as the grouping element:

h1 = {
  "admin_milestones"=>"1",
  "users_milestones"=>"0",
  "admin_goals"=>"1",
  "users_goals"=>"0", 
  "admin_tasks"=>"1", 
  "users_tasks"=>"0",
  "admin_messages"=>"1",
  "users_messages"=>"0",
  "admin_meetings"=>"1",
  "users_meetings"=>"0"
}

# group_by on the keys, then use the value from the hash as bucket
h2 = h1.keys.group_by { |k| h1[k] }

puts h2.inspect

Returns a hash from value to array of keys:

{
    "1" => [
        [0] "admin_milestones",
        [1] "admin_goals",
        [2] "admin_tasks",
        [3] "admin_messages",
        [4] "admin_meetings"
    ],
    "0" => [
        [0] "users_milestones",
        [1] "users_goals",
        [2] "users_tasks",
        [3] "users_messages",
        [4] "users_meetings"
    ]
}