我正在生成一系列像这样的哈希:
hash = Modality.joins(:exam).where(exams: {physician_id: physician}).map {|m|
{name: m.name, data: {m.exam.from_date => m.total}}
}
输出:
[
{:name=>"MR", :data=>{Sun, 01 Jan 2017=>44}},
{:name=>"CT", :data=>{Sun, 01 Jan 2017=>7}},
{:name=>"US", :data=>{Sun, 01 Jan 2017=>1}},
{:name=>"MR", :data=>{Wed, 01 Feb 2017=>41}},
{:name=>"CT", :data=>{Wed, 01 Feb 2017=>4}},
{:name=>"MR", :data=>{Wed, 01 Mar 2017=>66}},
{:name=>"CT", :data=>{Wed, 01 Mar 2017=>6}},
{:name=>"XR", :data=>{Wed, 01 Mar 2017=>1}},
{:name=>"CT", :data=>{Sat, 01 Apr 2017=>8}},
{:name=>"US", :data=>{Sat, 01 Apr 2017=>1}},
{:name=>"MR", :data=>{Sat, 01 Apr 2017=>73}}
]
我需要根据名称键对哈希的数据部分进行分组和合并,如下所示:
[
{:name=>"MR", :data=>{Sun, 01 Jan 2017=>44, Wed, 01 Feb 2017=>41, Wed, 01 Mar 2017=>66, Sat, 01 Apr 2017=>73}}
{:name=>"CT", :data=>{Sun, 01 Jan 2017=>7, Wed, 01 Feb 2017=>4, Wed, 01 Mar 2017=>6, Sat, 01 Apr 2017=>8}}
{:name=>"US", :data=>{Sun, 01 Jan 2017=>1, Sat, 01 Apr 2017=>1, Sun}}
{:name=>"XR", :data=>{Wed, 01 Mar 2017=>1}}
]
我尝试像这样缩小和合并:
exams = hash.group_by {|d| d[:name]}.map {|k, v| v.reduce(:merge)}
但这不是理想的输出:
[
{:name=>"MR", :data=>{Sun, 01 Jan 2017=>44}},
{:name=>"CT", :data=>{Sun, 01 Jan 2017=>7}},
{:name=>"US", :data=>{Sun, 01 Jan 2017=>1}},
{:name=>"XR", :data=>{Wed, 01 Mar 2017=>1}}
]
我如何正确合并此哈希?
答案 0 :(得分:1)
这是您的数组a
,我已将其缩小并将日期放在引号中。
arr = [
{:name=>"MR", :data=>{"Sun, 01 Jan 2017"=>44}},
{:name=>"CT", :data=>{"Sun, 01 Jan 2017"=>7}},
{:name=>"US", :data=>{"Sun, 01 Jan 2017"=>1}},
{:name=>"MR", :data=>{"Wed, 01 Feb 2017"=>41}},
{:name=>"CT", :data=>{"Wed, 01 Feb 2017"=>4}},
{:name=>"CT", :data=>{"Wed, 01 Mar 2017"=>6}},
{:name=>"XR", :data=>{"Wed, 01 Mar 2017"=>1}},
{:name=>"US", :data=>{"Sat, 01 Apr 2017=>1}}
]
将日期字符串转换为Date
个对象 1 需要进行简单修改,但我不会这样做,因为下面的方法不依赖于日期是字符串还是{ {1}}对象。
以下是获得所需回报值的两种方法。
Date
请注意arr.group_by { |h| h[:name] }.
map { |k,v| { name: k, data: v.reduce({}) { |h,g| h.merge(g[:data]) } } }
#=> [{:name=>"MR", :data=>{"Sun, 01 Jan 2017"=>44, "Wed, 01 Feb 2017"=>41}},
# {:name=>"CT", :data=>{"Sun, 01 Jan 2017"=>7, "Wed, 01 Feb 2017"=>4,
# "Wed, 01 Mar 2017"=>6}},
# {:name=>"US", :data=>{"Sun, 01 Jan 2017"=>1, "Sat, 01 Apr 2017"=>1}},
# {:name=>"XR", :data=>{"Wed, 01 Mar 2017"=>1}}]
会产生以下哈希值。
Enumerable#group_by
可以替代
arr.group_by { |h| h[:name] }
#=> {"MR"=>[{:name=>"MR", :data=>{"Sun, 01 Jan 2017"=>44}},
# {:name=>"MR", :data=>{"Wed, 01 Feb 2017"=>41}}],
# "CT"=>[{:name=>"CT", :data=>{"Sun, 01 Jan 2017"=>7}},
# {:name=>"CT", :data=>{"Wed, 01 Feb 2017"=>4}},
# {:name=>"CT", :data=>{"Wed, 01 Mar 2017"=>6}}],
# "US"=>[{:name=>"US", :data=>{"Sun, 01 Jan 2017"=>1}},
# {:name=>"US", :data=>{"Sun, 01 Jan 2017"=>1}}],
# "XR"=>[{:name=>"XR", :data=>{"Wed, 01 Mar 2017"=>1}}]}
与
v.reduce({}) { |h,g| h.merge(g[:data]) }
使用Hash#update(又名v.map { |h| h[:data] }.reduce(&:merge)
)和Hash#merge
merge!
这使用arr.each_with_object({}) do |g,h|
h.update(g[:name]=>g) { |_,n,o| { name: n[:name], data: n[:data].merge(o[:data]) } }
end.values
#=> [{:name=>"MR", :data=>{"Sun, 01 Jan 2017"=>44, "Wed, 01 Feb 2017"=>41}},
# {:name=>"CT", :data=>{"Sun, 01 Jan 2017"=>7, "Wed, 01 Feb 2017"=>4,
# "Wed, 01 Mar 2017"=>6}},
# {:name=>"US", :data=>{"Sun, 01 Jan 2017"=>1, "Sat, 01 Apr 2017"=>1}},
# {:name=>"XR", :data=>{"Wed, 01 Mar 2017"=>1}}]
的形式,它使用一个块来确定合并的两个哈希中存在的键的值。有关详细信息,请参阅方法文档,尤其是三个块变量Hash#update
,_
和o
的定义。 (第一个包含公共密钥的块变量在这里用下划线[有效的局部变量]表示,表示它不用于块计算。)
1 n