我有这样的哈希格式:
{"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个带有计数的字符串。最后,在给定日期发生的任何字符串都应出现在散列中。
我确信这是一种非常优雅的红宝石方式。请帮忙!
答案 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