ruby散列中相同值的总和

时间:2017-05-22 13:23:55

标签: ruby hash

大家。 我有哈希例如

{-2=>"a", -1=>"c", 1=>"a", 3=>"a", 49=>"a", -43=>"ab", 5=>"ab"}

可以有相同的价值观。我的任务是对值相等的键求和。结果:

{51=>"a", -1=>"c", -38=>"ab"}

我该怎么做?

hash.group_by{|key,val| val}

给出了糟糕的结果。

2 个答案:

答案 0 :(得分:4)

hash = {-2=>"a", -1=>"c", 1=>"a", 3=>"a", 49=>"a", -43=>"ab", 5=>"ab"}

hash.reduce({}) do |memo, (k,v)| 
  memo[v] ||= 0
  memo[v] += k
  memo
end.invert

# => {51=>"a", -1=>"c", -38=>"ab"}

reduce - 允许您通过迭代集合的值来构建新值,在本例中为hash。有关详情,请参阅docs

invert - 交换哈希的键和值。有关详情,请参阅docs

其他方法:

hash.reduce(Hash.new(0)) { |memo, (k,v)| memo[v] += k; memo }.invert

答案 1 :(得分:0)

h = {-2=>"a", -1=>"c", 1=>"a", 3=>"a", 49=>"a", -43=>"ab", 5=>"ab"}

然后

h.group_by(&:last).each_with_object({}) { |(k,v),h| h[v.map(&:first).sum] = k }
  #=> {51=>"a", -1=>"c", -38=>"ab"} 

但这会很疯狂,因为它依赖于独特的总和。 (回想一下哈希有唯一的密钥。)假设

h = {-54=>"a", -1=>"c", 1=>"a", 3=>"a", 49=>"a", -43=>"ab", 5=>"ab"}

然后

h.group_by(&:last).each_with_object({}) { |(k,v),h| h[v.map(&:first).sum] = k }
  #=> {-1=>"c", -38=>"ab"} 

-1=>"a"覆盖-1=<"c"。我怀疑这是想要的。

最好将h的内容保存在数组中:

a = [[-2, "a"], [-1, "c"], [-1, "a"], [49, "a"], [-43, "ab"],  [5, "ab"]]

(因为它允许整数的重复值 - 这里是-1),然后计算

a.group_by(&:last).each_with_object({}) { |(e,ar),h| h[e] = ar.map(&:first).sum }
  #=> {"a"=>46, "c"=>-1, "ab"=>-38}

请注意(对于h的原始值)

h.group_by(&:last)
  #=> {"a"=>[[-2, "a"], [1, "a"], [3, "a"], [49, "a"]],
  #    "c"=>[[-1, "c"]], "ab"=>[[-43, "ab"], [5, "ab"]]} 

v.map(&:first).sum可以替换为

v.reduce(0) { |t,(n,_)| t+n }