在汇总值时散列的数组

时间:2017-05-24 12:30:07

标签: ruby

我有一个数组如下:

[[172, 3], 
 [173, 1], 
 [174, 2], 
 [174, 3], 
 [174, 1]]

我希望转换为数组,但是在对匹配键的值进行求和时。所以我得到以下内容:

{172 => 3, 173 => 1, 174 => 6}

我将如何做到这一点?

4 个答案:

答案 0 :(得分:7)

  

我将如何做到这一点?

一次解决一个问题。

鉴于你的数组:

a = [[172, 3], [173, 1], [174, 2], [174, 3], [174, 1]]

我们需要一个额外的哈希:

h = {}

然后我们必须遍历数组中的对:

a.each do |k, v|
  if h.key?(k) # If the hash already contains the key
    h[k] += v  # we add v to the existing value
  else         # otherwise
    h[k] = v   # we use v as the initial value
  end
end

h #=> {172=>3, 173=>1, 174=>6}

现在让我们重构它。条件看起来有点麻烦,如果我们只想添加所有东西呢?

h = {}
a.each { |k, v| h[k] += v }
#=> NoMethodError: undefined method `+' for nil:NilClass

Bummer,这不起作用,因为哈希的值最初是nil。我们来解决这个问题:

h = Hash.new(0) # <- hash with default values of 0
a.each { |k, v| h[k] += v }
h #=> {172=>3, 173=>1, 174=>6}

看起来不错。我们甚至可以使用each_with_object

删除临时变量
a.each_with_object(Hash.new(0)) { |(k, v), h| h[k] += v }
#=> {172=>3, 173=>1, 174=>6}

答案 1 :(得分:3)

您可以尝试一下:

> array
#=> [[172, 3], [173, 1], [174, 2], [174, 3], [174, 1]]

array.group_by(&:first).map { |k, v| [k, v.map(&:last).inject(:+)] }.to_h
#=> => {172=>3, 173=>1, 174=>6}

Ruby 2.4.0版本:

a.group_by(&:first).transform_values { |e| e.sum(&:last) }
#=> => {172=>3, 173=>1, 174=>6}

答案 2 :(得分:1)

有关:

bcprov-jdk15on-1.47

您可以使用默认值为0的哈希

array = [[172, 3], [173, 1], [174, 2], [174, 3], [174, 1]]

然后使用它,并总结值:

hash = Hash.new{|h,k| h[k] = 0 }

答案 3 :(得分:1)

另一种可能的解决方案:

arr = [[172, 3], [173, 1], [174, 2], [174, 3], [174, 1]]

hash = arr.each_with_object({}) {|a,h| h[a[0]] = h[a[0]].to_i + a[1]}

p hash
# {172=>3, 173=>1, 174=>6}
相关问题