按ruby中的值组织哈希散列

时间:2014-09-21 20:32:58

标签: ruby hash

我有这样的哈希格式:

{"string1" => 
  {date1 => 1, 
   date2 => 21, 
   date3 => 9},
"string2" =>
  {date1 => 23,
   date2 => 88,
   date3 => 2},
"string3" =>
  {date1 => 0,
   date2 => 0,
   date3 => 5}
}

它告诉我:“这个字符串,在这个日期,发生了很多次。”我想像这样重新排序:

{date1 =>
 {"string1" => 1,
  "string2" => 23},
date2 =>
 {"string1" => 21,
  "string2" => 88},
date3 => 
 {"string1" => 9,
  "string2" => 2,
  "string3" => 5}
}

所以现在它告诉我:“在这个日期,这个字符串发生了很多次”。某些日期可能会有许多带有计数的字符串,而其他日期可能会有0个带有计数的字符串。最后,在给定日期发生的任何字符串都应出现在散列中。

我确信这是一种非常优雅的红宝石方式。请帮忙!

2 个答案:

答案 0 :(得分:1)

我相信这可以做你想要的。

h = {"string1" => {"date1" => 1,  "date2" => 21, "date3" => 9},
     "string2" => {"date1" => 23, "date2" => 88, "date3" => 2},
     "string3" => {"date1" => 0,  "date2" => 0,  "date3" => 5}}

h.each_with_object({}) { |(k,v),g| v.each { |d,vv|
  (g[d] ||= {}).update({ k=>vv }) } }
  #=> {"date1"=>{"string1"=>1,  "string2"=>23, "string3"=>0},
  #    "date2"=>{"string1"=>21, "string2"=>88, "string3"=>0},
  #    "date3"=>{"string1"=>9,  "string2"=>2,  "string3"=>5}}

如果您不希望值为零的对,请先执行此操作:

h.each { |k,v| v.delete_if { |_,vv| vv.zero? } }
  #=> {"string1"=>{"date1"=>1, "date2"=>21, "date3"=>9},
  #    "string2"=>{"date1"=>23, "date2"=>88, "date3"=>2},
  #    "string3"=>{"date3"=>5}}

h.each_with_object({}) { |(k,v),g| v.each { |d,vv|
  (g[d] ||= {}).update({ k=>vv }) } }
  #=> {"date1"=>{"string1"=>1,  "string2"=>23},
  #    "date2"=>{"string1"=>21, "string2"=>88},
  #    "date3"=>{"string1"=>9,  "string2"=>2, "string3"=>5}}

我已将datex作为字符串。如果它们是Date个对象(或符号等),则表达式也不例外。

答案 1 :(得分:1)

这是另一种方法:

res = Hash.new { |h, k| h[k] = {} }
hash.each do |kstring, datehash|
  datehash.each { |kdate, n| n == 0 ? res[kdate] : res[kdate][kstring] = n }
end