簡體   English   中英

Ruby-如何根據給定日期(=鍵)對哈希值求和?

[英]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, 

這個怎么做?

先感謝您。

您可以嘗試使用selectsum

@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 :: strptimeBigDecimal :: new

按月求和BigDecimal

現在,我們可以使用Hash#rejectEnumerable#group_byEnumerable#mapEnumerable#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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM