【问题标题】:Group & sum hashes by month, including when no data按月对哈希进行分组和求和,包括没有数据时
【发布时间】:2014-04-18 16:29:49
【问题描述】:

我有一个用于查询数据库的日期范围。返回的结果是一个哈希数组,如下所示:

[
  {:created=>"2013-12-10", :amount=>1}, 
  {:created=>"2014-02-20", :amount=>1}, 
  {:created=>"2014-02-23", :amount=>4}, 
  {:created=>"2014-02-24", :amount=>1}, 
  {:created=>"2014-03-06", :amount=>1}, 
  {:created=>"2014-03-14", :amount=>3}, 
  {:created=>"2014-03-15", :amount=>1}, 
  {:created=>"2014-03-17", :amount=>1}, 
  {:created=>"2014-03-20", :amount=>1}, 
  {:created=>"2014-03-21", :amount=>1}, 
  {:created=>"2014-03-24", :amount=>1}, 
  {:created=>"2014-03-25", :amount=>1}, 
  {:created=>"2014-03-28", :amount=>1}, 
  {:created=>"2014-04-05", :amount=>1}, 
  {:created=>"2014-04-07", :amount=>1}
] 

我需要做的是按月对amount 进行分组和求和,如果一个月没有数据但属于初始范围的一部分,则显示0

所以在我上面的例子中,我查询数据库的日期范围是2013-11-132014-04-18

输出最终只是按月份分组并求和的基本数据数组。所以上面的例子应该产生:

[0, 1, 0, 6, 11, 2]

这些数组项对应于:11 月、12 月、1 月、2 月、3 月、4 月。

FWIW,我正在运行 Ruby 2.0.0,这是 Rails 4 应用程序的一部分,如果碰巧有一些特殊的 Rails 辅助方法在这里有用的话。

【问题讨论】:

    标签: ruby-on-rails ruby


    【解决方案1】:

    您可以使用#group_by方法按年、月分组,然后组合#map#uniq#reduce得到正确的Array

    # grouping record by year and month, and then sorting them
    g = a.group_by {|v| Date.parse(v[:created][0,7] + '-01') }.sort
    
    # generating a result hash
    h = Hash[g]
    
    # generating range
    range = Date.new(2013,11)..Date.new(2014,04)
    
    # here we firstly remap to get *year-month* list by dates, which will contain only
    # one date per month, then we calculate sum for each month value.
    range.to_a.map {|d| Date.new(d.year,d.month,1)}.uniq.map {|d| h[d] && h[d].reduce(0) {|sum,h| sum + h[:amount]} || 0 }
    
    # => [0, 1, 0, 6, 11, 2] 
    

    对于,您可以使用#try 方法:

    range.to_a.map {|d| Date.new(d.year,d.month,1)}.uniq.map {|d| h[d].try(:reduce, 0) {|sum,h| sum + h[:amount]} || 0 }
    

    【讨论】:

    • 除非我遗漏了什么……这根本不是我想要的。如前所述,需要对数据求和,并且需要考虑缺失的月份。
    • 我实际上刚刚意识到了一个无法使用的用例。取初始日期范围。在我的示例中,我提到了从2013-11-13 开始的范围。如果 11 月份没有数据,这将不起作用。
    • @Shpigford 所以不能计算 2013-11-13 之前的日期吗?还是什么?
    • 好吧,他们不会被拉到查询中。我的数据库查询示例的日期范围从2013-11-13 开始。所以说从 2013-11-13 到 2013-11-31 没有记录...我仍然需要在该月的最终数组中显示“0”。
    • @Shpigford 但是您在测试请求中有它:{:created=>"2013-11-16", :amount=>1}, 不是;它不是正确的数据吗?
    猜你喜欢
    • 2011-05-26
    • 2019-02-14
    • 1970-01-01
    • 1970-01-01
    • 2020-03-22
    • 2019-04-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多