如何对哈希数组按partner_id分组并求和value属性?
解决Ruby哈希数组按partner_id分组并累加value的问题
你的需求很明确——把给定的哈希数组按partner_id分组,然后累加每组的value值。咱们先看看你原来的代码哪里出了问题,再给出几种靠谱的解决方法。
原代码的问题分析
你写的代码有两个核心问题:
- 没有初始化一个空哈希来存储分组后的结果,循环里的
hash要么被直接赋值为单个元素哈希,要么未定义,导致逻辑完全混乱; - 就算
hash存在,你修改的是hash[:value],而不是对应partner_id分组下的value,逻辑方向错了。
方法一:用group_by + map(最简洁直观)
这是Ruby处理分组累加最常用的方式,代码可读性很高:
res = [ {:partner_name=>"company 1", :partner_id=>787, :value=>1}, {:partner_name=>"company 2", :partner_id=>768, :value=>1}, {:partner_name=>"company 3", :partner_id=>769, :value=>1}, {:partner_name=>"company 1", :partner_id=>787, :value=>2} ] result = res.group_by { |item| item[:partner_id] }.map do |id, items| { partner_name: items.first[:partner_name], partner_id: id, value: items.sum { |item| item[:value] } } end puts result.inspect # 输出:[{:partner_name=>"company 1", :partner_id=>787, :value=>3}, {:partner_name=>"company 2", :partner_id=>768, :value=>1}, {:partner_name=>"company 3", :partner_id=>769, :value=>1}]
步骤解释:
group_by { |item| item[:partner_id] }会把原数组按partner_id分组,得到一个键为partner_id、值为对应哈希数组的临时哈希;- 用
map遍历这个临时哈希,对每个分组:- 取分组内第一个元素的
partner_name(默认同一个partner_id对应相同名称,如果有名称不一致的情况,可以额外处理,比如取唯一值); - 保留当前分组的
partner_id; - 用
sum累加该分组所有元素的value。
- 取分组内第一个元素的
方法二:用each_with_object(更灵活的累加方式)
如果你需要更灵活的逻辑控制,比如处理名称不一致的情况,这个方法更合适:
result = res.each_with_object({}) do |item, hash| key = item[:partner_id] if hash.key?(key) hash[key][:value] += item[:value] # 可选:如果存在名称不一致的情况,可以在这里做处理,比如拼接名称 # hash[key][:partner_name] = "#{hash[key][:partner_name]} / #{item[:partner_name]}" else hash[key] = item.dup # 复制原哈希,避免修改原数组的元素 end end.values puts result.inspect
步骤解释:
each_with_object({})初始化一个空哈希作为累加容器;- 遍历每个元素,用
partner_id作为哈希的键; - 如果键已存在,就累加对应分组的
value;如果不存在,就复制当前元素存入哈希(用dup是为了防止后续修改影响原数组的元素); - 最后用
.values取出哈希里的所有值,就是我们需要的结果数组。
内容的提问来源于stack exchange,提问作者Mongoid
相关产品推荐
相关产品推荐

