【问题标题】:Convert Array to Hash removing duplicate keys and adding values at the same time将 Array 转换为 Hash 删除重复键并同时添加值
【发布时间】: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 的提示

标签: ruby arrays hash enumerable


【解决方案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 方法!那是拉德。
猜你喜欢
  • 1970-01-01
  • 2023-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-22
  • 2019-09-03
  • 2022-08-17
相关资源
最近更新 更多