将数组转换为哈希,同时删除重复键和添加值
Convert Array to Hash removing duplicate keys and adding values at the same time
我有一个数组,如下所示:
f = [["Wed, 12-31", 120.0],["Thu, 01-01", 120.0], ["Thu, 01-01", 120.0]]
我可以将其转换为散列并删除重复键:
h = Hash[ *f.collect { |v| [v] }.flatten ]
# => {"Wed, 12-31"=>120.0, "Thu, 01-01"=>120.0}
差不多了,但我想对具有相同日期字符串的元素的值求和,上述数组的期望结果是:
{"Wed, 12-31"=>120.0, "Thu, 01-01"=>240.0}
我怎样才能做到这一点?
这个有效:
result = Hash.new(0)
f = [["Wed, 12-31", 120.0],["Thu, 01-01", 120.0], ["Thu, 01-01", 120.0]]
f.each { |subarray| result[subarray[0]] += subarray[1] }
puts result
如果你想要花哨的,你可以使用.inject()
我会使用 each_with_object
:
ary = [["Wed, 12-31", 120.0], ["Thu, 01-01", 120.0], ["Thu, 01-01", 120.0]]
hash = ary.each_with_object(Hash.new(0)){ |(k,v), h| h[k] += v }
=> {"Wed, 12-31"=>120.0, "Thu, 01-01"=>240.0}
解决此类问题的另一种标准方法是使用 Enumerable#group_by:
Hash[ary.group_by(&:first).map { |d,a| [d, a.reduce(0) { |t,(_,n)| t+n }] }]
#=> {"Wed, 12-31"=>120.0, "Thu, 01-01"=>240.0}
我们有:
a = ary.group_by(&:first)
#=> {"Wed, 12-31"=>[["Wed, 12-31", 120.0]],
# "Thu, 01-01"=>[["Thu, 01-01", 120.0], ["Thu, 01-01", 120.0]]}
b = a.map { |d,a| [d, a.reduce(0) { |t,(_,n)| t+n }] }
#=> [["Wed, 12-31", 120.0], ["Thu, 01-01", 240.0]]
Hash[b]
#=> {"Wed, 12-31"=>120.0, "Thu, 01-01"=>240.0}
或 Ruby 2.0+:
b.to_h
#=> {"Wed, 12-31"=>120.0, "Thu, 01-01"=>240.0}
一个变体是:
ary.group_by(&:first).map { |d,a| [d, a.transpose.last.reduce(:+) ] }.to_h
我有一个数组,如下所示:
f = [["Wed, 12-31", 120.0],["Thu, 01-01", 120.0], ["Thu, 01-01", 120.0]]
我可以将其转换为散列并删除重复键:
h = Hash[ *f.collect { |v| [v] }.flatten ]
# => {"Wed, 12-31"=>120.0, "Thu, 01-01"=>120.0}
差不多了,但我想对具有相同日期字符串的元素的值求和,上述数组的期望结果是:
{"Wed, 12-31"=>120.0, "Thu, 01-01"=>240.0}
我怎样才能做到这一点?
这个有效:
result = Hash.new(0)
f = [["Wed, 12-31", 120.0],["Thu, 01-01", 120.0], ["Thu, 01-01", 120.0]]
f.each { |subarray| result[subarray[0]] += subarray[1] }
puts result
如果你想要花哨的,你可以使用.inject()
我会使用 each_with_object
:
ary = [["Wed, 12-31", 120.0], ["Thu, 01-01", 120.0], ["Thu, 01-01", 120.0]]
hash = ary.each_with_object(Hash.new(0)){ |(k,v), h| h[k] += v }
=> {"Wed, 12-31"=>120.0, "Thu, 01-01"=>240.0}
解决此类问题的另一种标准方法是使用 Enumerable#group_by:
Hash[ary.group_by(&:first).map { |d,a| [d, a.reduce(0) { |t,(_,n)| t+n }] }]
#=> {"Wed, 12-31"=>120.0, "Thu, 01-01"=>240.0}
我们有:
a = ary.group_by(&:first)
#=> {"Wed, 12-31"=>[["Wed, 12-31", 120.0]],
# "Thu, 01-01"=>[["Thu, 01-01", 120.0], ["Thu, 01-01", 120.0]]}
b = a.map { |d,a| [d, a.reduce(0) { |t,(_,n)| t+n }] }
#=> [["Wed, 12-31", 120.0], ["Thu, 01-01", 240.0]]
Hash[b]
#=> {"Wed, 12-31"=>120.0, "Thu, 01-01"=>240.0}
或 Ruby 2.0+:
b.to_h
#=> {"Wed, 12-31"=>120.0, "Thu, 01-01"=>240.0}
一个变体是:
ary.group_by(&:first).map { |d,a| [d, a.transpose.last.reduce(:+) ] }.to_h