[英]Ruby - How to sum values of a hash based on a given date (=key)?
我在哈希中有這些值:
{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年1月:哈希中所有1月項目的總和
具體來說,這些總和:
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,
這個怎么做?
先感謝您。
您可以嘗試使用select
和sum
:
@dates.select{|d, _| d.strftime('%Y %m') == '2016 01'}.values.sum
構造示例哈希
首先,讓我們構造一個與您的哈希值相似但略小一些的哈希值( 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 :: strptime和BigDecimal :: new 。
按月求和BigDecimal
值
現在,我們可以使用Hash#reject , Enumerable#group_by , Enumerable#map , Enumerable#reduce (又名inject
)和Array#to_h來獲取所需的結果:
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
進行比較。
我使用Hash#merge的形式,該形式采用一個塊來確定要合並的兩個哈希中存在的鍵的值。 當我將sums
與其自身合並時,該塊用於確定所有鍵的值。
一旦你的哈希sums
這是一個容易的任務來打印由月和年總計在任何你想要的格式。
步驟
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)>}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.