You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ruby哈希数组按name分组合并data哈希的正确方法

问题:按Name分组合并哈希数组中的Data字段

我现在需要处理一个Ruby哈希数组,通过这段代码生成了初始数据:

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键分组,把每个分组里的:data哈希合并起来,得到这样的结果:

[ {: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}}, {:name=>"XR", :data=>{Wed, 01 Mar 2017=>1}} ]

我试过这段代码:

exams = hash.group_by {|d| d[:name]}.map {|k, v| v.reduce(:merge)}

但结果不对,只保留了每个分组里第一个元素的:data:

[ {: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}} ]

请问怎么才能正确实现这种哈希合并?


解决方案

问题出在v.reduce(:merge)上:默认的Hash#merge会直接覆盖相同键的值,当你合并整个元素哈希时,后面元素的:data会直接替换前面的,而不是合并内部的键值对。我们需要单独处理:data的合并,而不是合并整个元素哈希。

方法一:用each_with_object合并数据

exams = hash.group_by { |d| d[:name] }.map do |name, entries|
  combined_data = entries.each_with_object({}) do |entry, acc|
    acc.merge!(entry[:data])
  end
  { name: name, data: combined_data }
end

方法二:用reduce简洁实现

exams = hash.group_by { |d| d[:name] }.map do |name, entries|
  {
    name: name,
    data: entries.reduce({}) { |acc, entry| acc.merge(entry[:data]) }
  }
end

方法三:Ruby 2.6+ 用transform_values简化

如果你的Ruby版本是2.6及以上,可以用transform_values让代码更简洁:

exams = hash.group_by { |d| d[:name] }.transform_values do |entries|
  entries.reduce({}) { |acc, e| acc.merge(e[:data]) }
end.map { |name, data| { name: name, data: data } }

这几种方法都会把每个分组下的所有:data哈希合并成一个完整的哈希,最终得到你想要的分组结果。


内容的提问来源于stack exchange,提问作者bradbajuz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:16:54