2017-05-24 28 views
0

我有一個陣列如下:陣列哈希而求和值

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

即我想轉換成一個數組,但同時匹配鍵求和的值。所以我會得到以下幾點:

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

我該怎麼做呢?

+0

歡迎來到Stack Overflow。請閱讀「[問]」和「[mcve]」以及鏈接的頁面。首先,我們需要看到你的努力的證據。沒有它,看起來你沒有嘗試並希望我們爲你做。 –

回答

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} 
+0

哇,你甚至經歷了不工作的部分,以顯示推理+1 – Mark

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} 
+0

'transform_values'是在2.4中引入的嗎?我一定忽略了它。很有用! :-) – Stefan

+0

@Stefan yeap,在2.4.0 :) –

1

爲:

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

你可以使用一個哈希用默認值0喜歡這

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

然後使用它,並總結了值:

array.each { |a, b| hash[a] += b } 

#=> {172=>3, 173=>1, 174=>6} 
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}