将 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 删除重复键并同时添加值的主要内容,如果未能解决你的问题,请参考以下文章

根据值删除数组键的简单方法[重复]

向下转换并同时从 const 转换为 non-const

MapReduce深入

从 CArchive 读取 WORD 变量并同时转换为 int

如何将 ArrayList 转换为 Array [重复]

将对象转换为数组 - 维护命名键