2014-04-18 45 views
0

我有一个日期范围,我正用它来查询数据库。返回的结果是哈希的数组,像这样:按月分组和总计哈希,包括当没有数据时

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

回答

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 } 
+0

除非我错过了一些东西......这不是我一直在寻找的东西。如前所述,数据需要汇总,需要考虑遗漏的月份。 – Shpigford

+0

@Shpigford更新 –

+0

谢谢。你介意解释它是如何工作的吗? – Shpigford