Групповое хеш по значениям в рубине

У меня есть хэш в рубине, который выглядит примерно так:

{
  "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"
}

Я пытаюсь найти решения, которые могут разрезать этот хэш на две части: одну со значением 1 и другим хешем со значением 0.

Ответ 1

Вы можете группировать хэш по его значению:

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}

Он создаст хэш, сгруппированный по его значениям следующим образом:

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"]]} 

Ответ 2

Если вам нужен массив как ответ, самым чистым решением является метод разделения.

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

Ответ 3

Просто 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", ...}

Возвращаемое значение зависит от вашей версии Ruby. Ruby 1.8 возвращает массив массивов, тогда как Ruby 1.9 возвращает хеш, как в примере выше.

Ответ 4

Вы должны использовать group_by для массивов keys и использовать значение в качестве элемента группировки:

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

Возвращает хеш от значения к массиву ключей:

{
    "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"
    ]
}