大家。 我有哈希例如
{-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}
给出了糟糕的结果。
答案 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 }