按月分组和总和,包括没有数据时

我有一个日期范围,我用来查询数据库。 返回的结果是像这样的哈希数组:

[ {: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辅助方法在这里很有用。

您可以使用#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] 

对于rails,你可以使用#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 }