将 Array 转换为 Hash 删除重复键并同时添加值
Posted
技术标签:
【中文标题】将 Array 转换为 Hash 删除重复键并同时添加值【英文标题】:Convert Array to Hash removing duplicate keys and adding values at the same time 【发布时间】:2015-02-28 09:14:26 【问题描述】:我有一个如下所示的数组:
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
我怎样才能做到这一点?
【问题讨论】:
注意,您可以将您的数组转换为一个哈希丢弃重复键,而无需.collect.flatten
废话。只需使用Hash[array]
。 f.collect |v| [v]
只是将数组映射到自身。它不做任何事情。 .flatten
在已经平坦的阵列上同样没用。
@KennyMeyer 错了,谷歌? google.ca/…
感谢.collect
和.flatten
的提示
【参考方案1】:
这行得通:
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
而不是inject
。它工作得更干净。【参考方案2】:
我会使用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
【讨论】:
我想补充一点,虽然我接受了@kennymeyer 的回答,但后来我改用了这个解决方案。 只是重申您偶尔会在 Stack Overflow 上看到的内容:不要选择出现的第一个答案并回答您的问题。有很多方法可以做某事,而且人们不会在他们的电脑前准备好等待突然提出问题。答案有时需要一段时间才能形成;我经常等着回答,希望有人会用我认为正确的方式来做某事,然后如果没有人做过或回答得像我认为的那样彻底,我会添加我的答案。所以,问问,然后等一天,看看会出现什么。【参考方案3】:解决此类问题的另一种标准方法是使用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
【讨论】:
感谢 Ruby 的 2.0+to_h
方法!那是拉德。以上是关于将 Array 转换为 Hash 删除重复键并同时添加值的主要内容,如果未能解决你的问题,请参考以下文章