2016-03-23 27 views
0

私はハッシュでこれらの値を持っている:Ruby - 与えられた日付(=キー)に基づいてハッシュの値を合計する方法は?

{nil=>0, 
Thu, 03 Dec 2015=>#<BigDecimal:7ff496381db8,'0.151875E2',18(27)>, 
Fri, 04 Dec 2015=>#<BigDecimal:7ff496381cf0,'0.214375E2',18(27)>, 
Wed, 09 Dec 2015=>#<BigDecimal:7ff496381c28,'0.6229E2',18(27)>, 
Thu, 10 Dec 2015=>#<BigDecimal:7ff496381b60,'0.1243E2',18(27)>, 
Fri, 11 Dec 2015=>#<BigDecimal:7ff496381a98,'0.1243E2',18(27)>, 
Mon, 14 Dec 2015=>#<BigDecimal:7ff4963819d0,'0.6611E2',18(27)>, 
Tue, 15 Dec 2015=>#<BigDecimal:7ff496381908,'0.625E1',18(18)>, 
Wed, 16 Dec 2015=>#<BigDecimal:7ff496381840,'0.73345E2',18(27)>, 
Thu, 17 Dec 2015=>#<BigDecimal:7ff496381778,'0.31845E2',18(27)>, 
Fri, 18 Dec 2015=>#<BigDecimal:7ff4963816b0,'0.409225E2',18(27)>, 
Mon, 21 Dec 2015=>#<BigDecimal:7ff4963815e8,'0.8019E2',18(27)>, 
Mon, 28 Dec 2015=>#<BigDecimal:7ff496381520,'0.3125E2',18(27)>, 
Mon, 04 Jan 2016=>#<BigDecimal:7ff496381458,'0.125E2',18(27)>, 
Wed, 06 Jan 2016=>#<BigDecimal:7ff496381390,'0.625E2',18(27)>, 
Thu, 07 Jan 2016=>#<BigDecimal:7ff4963812c8,'0.9111E2',18(27)>, 
Fri, 08 Jan 2016=>#<BigDecimal:7ff4963811d8,'0.11972E3',18(27)>, 
Mon, 11 Jan 2016=>#<BigDecimal:7ff4963810e8,'0.5022E2',18(27)>, 
Wed, 13 Jan 2016=>0, Thu, 14 Jan 2016=>0, Fri, 15 Jan 2016=>0, 
Wed, 09 Mar 2016=>#<BigDecimal:7ff496380eb8,'0.258125E2',18(27)>, 
Tue, 15 Mar 2016=>#<BigDecimal:7ff496380da0,'0.631825E2',18(27)>, 
Wed, 16 Mar 2016=>#<BigDecimal:7ff496380cd8,'0.504225E2',18(27)>, 
Thu, 17 Mar 2016=>#<BigDecimal:7ff496380c10,'0.125E2',18(27)>, 
Fri, 18 Mar 2016=>#<BigDecimal:7ff496380b48,'0.631825E2',18(27)>, 
Mon, 21 Mar 2016=>#<BigDecimal:7ff496380a80,'0.167925E2',18(27)>, 
Tue, 22 Mar 2016=>0} 

私はいくつかのカレンダーデータ(@dates)をループしていると私は、特定の年と月を含む二つの変数を取得ここから:今

@dates.each do |d| 
    current_yer = d.strftime('%Y') #2016 
    current_month = d.strftime('%m') # 01 - january 

を、私は日付を含む変数を持っている、私はハッシュのすべてのデータの合計を印刷したいと思います。したがって、この場合には、私は出力として、このような何かを取得したいと思います:

2016 01:

特にハッシュ内のすべての1月の項目のSUM、これらのSUM:

Mon, 04 Jan 2016=>#<BigDecimal:7ff496381458,'0.125E2',18(27)>, 

Wed, 06 Jan 2016=>#<BigDecimal:7ff496381390,'0.625E2',18(27)>, 

Thu, 07 Jan 2016=>#<BigDecimal:7ff4963812c8,'0.9111E2',18(27)>, 

Fri, 08 Jan 2016=>#<BigDecimal:7ff4963811d8,'0.11972E3',18(27)>, 

Mon, 11 Jan 2016=>#<BigDecimal:7ff4963810e8,'0.5022E2',18(27)>, 

Wed, 13 Jan 2016=>0, Thu, 14 Jan 2016=>0, Fri, 15 Jan 2016=>0, 

これを行う方法?

ありがとうございます。

答えて

1

あなたはselectsumで試すことができます。

@dates.select{|d, _| d.strftime('%Y %m') == '2016 01'}.values.sum 
+0

注意。 –

0

のはあなたに似ていますが、少し小さいハッシュ(h)を構築しましょう例のハッシュ

ファーストを構築:

g = { 
    "Thu, 03 Dec 2015"=> 1, 
    "Fri, 11 Dec 2015"=> 2, 
    "Mon, 14 Dec 2015"=> 3, 
    "Tue, 15 Dec 2015"=> 4, 
    "Wed, 16 Dec 2015"=> 5, 
    "Fri, 18 Dec 2015"=> 6, 
    "Mon, 21 Dec 2015"=> 7, 
    "Mon, 04 Jan 2016"=> 8, 
    "Fri, 08 Jan 2016"=> 9, 
    "Wed, 13 Jan 2016"=> 0, 
    "Thu, 14 Jan 2016"=> 0, 
    "Wed, 09 Mar 2016"=>10, 
    "Tue, 15 Mar 2016"=>11, 
    "Wed, 16 Mar 2016"=>12, 
    "Mon, 21 Mar 2016"=>13, 
    "Tue, 22 Mar 2016"=> 0 } 

require 'date' 
require 'bigdecimal' 

h = { nil=>0 }.tap { |h| g.each { |k,v| 
    h[Date.strptime(k, "%a, %d %b %Y")] = v.zero? ? 0 : BigDecimal.new(v) } } 

#=> {nil=>0, 
    # #<Date: 2015-12-03 ((2457360j,0s,0n),+0s,2299161j)> => 
    #  #<BigDecimal:7faef915c8e0,'0.1E1',9(27)>, 
    # #<Date: 2015-12-11 ((2457368j,0s,0n),+0s,2299161j)> => 
    #  #<BigDecimal:7faef914ff28,'0.2E1',9(27)>, 
    # #<Date: 2015-12-14 ((2457371j,0s,0n),+0s,2299161j) >=> 
    #  #<BigDecimal:7faef914f938,'0.3E1',9(27)>, 
    # #<Date: 2015-12-15 ((2457372j,0s,0n),+0s,2299161j)> => 
    #  #<BigDecimal:7faef914f7a8,'0.4E1',9(27)>, 
    # #<Date: 2015-12-16 ((2457373j,0s,0n),+0s,2299161j)> => 
    #  #<BigDecimal:7faef914f320,'0.5E1',9(27)>, 
    # #<Date: 2015-12-18 ((2457375j,0s,0n),+0s,2299161j)> => 
    #  #<BigDecimal:7faef914e8d0,'0.6E1',9(27)>, 
    # #<Date: 2015-12-21 ((2457378j,0s,0n),+0s,2299161j)> => 
    #  #<BigDecimal:7faef914dde0,'0.7E1',9(27)>, 
    # #<Date: 2016-01-04 ((2457392j,0s,0n),+0s,2299161j)> => 
    #  #<BigDecimal:7faef914dca0,'0.8E1',9(27)>, 
    # #<Date: 2016-01-08 ((2457396j,0s,0n),+0s,2299161j)> => 
    #  #<BigDecimal:7faef914d390,'0.9E1',9(27)>, 
    # #<Date: 2016-01-13 ((2457401j,0s,0n),+0s,2299161j)> => 
    #  0, 
    # #<Date: 2016-01-14 ((2457402j,0s,0n),+0s,2299161j)> => 
    #  0, 
    # #<Date: 2016-03-09 ((2457457j,0s,0n),+0s,2299161j)> => 
    #  #<BigDecimal:7faef914cd28,'0.1E2',9(27)>, 
    # #<Date: 2016-03-15 ((2457463j,0s,0n),+0s,2299161j)> => 
    #  #<BigDecimal:7faef913ff60,'0.11E2',9(27)>, 
    # #<Date: 2016-03-16 ((2457464j,0s,0n),+0s,2299161j)> => 
    #  #<BigDecimal:7faef913f8d0,'0.12E2',9(27)>, 
    # #<Date: 2016-03-21 ((2457469j,0s,0n),+0s,2299161j)> => 
    #  #<BigDecimal:7faef913f560,'0.13E2',9(27)>, 
    # #<Date: 2016-03-22 ((2457470j,0s,0n),+0s,2299161j)> => 
    #  0 
} 

ここでは、クラスメソッドDate::strptimeBigDecimal::newを使用しました。

合計私たちは今、あなたが必要な結果を得るために、Hash#rejectEnumerable#group_byEnumerable#mapEnumerable#reduce(別名inject)とArray#to_hを使用することができ、月によってBigDecimal

sums = 
h.reject { |k,_| k.nil? }. 
    group_by { |k,_| [k.year, k.month] }. 
    map { |yr_and_mon, arr| [yr_and_mon, arr.reduce(0) { |t,(_,bd)| t+bd }] }. 
    to_h 
    #=> {[2015, 12]=>#<BigDecimal:7faef9197eb8,'0.28E2',9(18)>, 
    # [2016, 1]=>#<BigDecimal:7faef9197b70,'0.17E2',9(18)>, 
    # [2016, 3]=>#<BigDecimal:7faef9197760,'0.46E2',9(18)>} 

我々がいることがわかりBigDecimalの値を整数に変換する方が簡単です。

sums.merge(sums) { |*,v| v.to_i } 
    #=> {[2015, 12]=>28, [2016, 1]=>17, [2016, 3]=>46} 

これらの結果をハッシュgとこの回答の冒頭で比較してください。

ブロックを使用して、両方のハッシュがマージされているときに存在するキーの値を決定する形式を使用しました。私はsumsをそれ自身とマージしているので、ブロックはすべてのキーの値を決定するために使われます。

ハッシュを取得したら、sumsは、月と年の合計を任意の形式で簡単に印刷できます。`@のdates`」キーのいずれかが` nil`であることを

手順

h1 = h.reject { |k,_| k.nil? }.group_by { |k,_| [k.year, k.month] } 
    #=> {[2015, 12]=>[[#<Date: 2015-12-03 ((2457360j,0s,0n),+0s,2299161j)>, 
    #     #<BigDecimal:7faef915c8e0,'0.1E1',9(27)>], 
    #     [#<Date: 2015-12-11 ((2457368j,0s,0n),+0s,2299161j)>, 
    #     #<BigDecimal:7faef914ff28,'0.2E1',9(27)>], 
    ... 
    #     #<BigDecimal:7faef9093850,'0.46E2',9(18)>]] 
a1 = h1.map { |yr_and_mon, arr| [yr_and_mon, arr.reduce(0) { |t,(_,bd)| t+bd }] } 
    #=> [[[2015, 12], #<BigDecimal:7faef9029dd8,'0.28E2',9(18)>], 
    # [[2016, 1], #<BigDecimal:7faef90296a8,'0.17E2',9(18)>], 
    # [[2016, 3], #<BigDecimal:7faef9028dc0,'0.46E2',9(18)>]] 
a1.to_h 
    #=> {[2015, 12]=>#<BigDecimal:7faef9098710,'0.28E2',9(18)>, 
    # [2016, 1]=>#<BigDecimal:7faef9093da0,'0.17E2',9(18)>, 
    # [2016, 3]=>#<BigDecimal:7faef9093850,'0.46E2',9(18)>} 
関連する問題