按业务年度的`:date`值对哈希数组进行分组

时间:2015-01-10 21:38:59

标签: ruby arrays hash

我有一个哈希数组,每个哈希都有date个键,如下所示:

data = [
        {date: Date.new(2012,1), name: "1"},
        {date: Date.new(2012,8), name: "2"},
        {date: Date.new(2013,2), name: "3"},
        {date: Date.new(2013,6), name: "4"},
        {date: Date.new(2013,9), name: "5"},
        {date: Date.new(2014,3), name: "6"},
        {date: Date.new(2014,4), name: "7"},
        {date: Date.new(2014,8), name: "8"},
       ]

我想按业务年度对哈希进行分组,换句话说就是4月到明年3月这样:

[
 [{date: Date.new(2012,1), name: "1"}],
 [{date: Date.new(2012,8), name: "2"},
  {date: Date.new(2013,2), name: "3"}],
 [{date: Date.new(2013,6), name: "4"},
  {date: Date.new(2013,9), name: "5"},
  {date: Date.new(2014,3), name: "6"}],
 [{date: Date.new(2014,4), name: "7"},
  {date: Date.new(2014,8), name: "8"}]
]

要完成我这样写的:

result = []
4.times do |i|
  result[i] = []
  data.each do |datum|
    result[i] << datum if datum[:date].between?(Date.new(2011+i,4), Date.new(2012+i,3)) 
  end
end

但是这段代码只有在我知道我处理的时间范围时才有效。 我觉得有更好的方法可以更简洁地在Ruby中编写它。

我该如何写这个函数?

1 个答案:

答案 0 :(得分:3)

您可以使用Enumerable#group_by

require 'date'

data.group_by { |h| (h[:date].month > 3) ? h[:date].year : h[:date].year - 1 }
  #=> {2011=>[{:date=>#<Date: 2012-01-01 ((2455928j,0s,0n),+0s,2299161j)>, :name=>"1"}],
  #    2012=>[{:date=>#<Date: 2012-08-01 ((2456141j,0s,0n),+0s,2299161j)>, :name=>"2"},
  #           {:date=>#<Date: 2013-02-01 ((2456325j,0s,0n),+0s,2299161j)>, :name=>"3"}],
  #    2013=>[{:date=>#<Date: 2013-06-01 ((2456445j,0s,0n),+0s,2299161j)>, :name=>"4"},
  #           {:date=>#<Date: 2013-09-01 ((2456537j,0s,0n),+0s,2299161j)>, :name=>"5"},
  #           {:date=>#<Date: 2014-03-01 ((2456718j,0s,0n),+0s,2299161j)>, :name=>"6"}],
  #    2014=>[{:date=>#<Date: 2014-04-01 ((2456749j,0s,0n),+0s,2299161j)>, :name=>"7"},
  #           {:date=>#<Date: 2014-08-01 ((2456871j,0s,0n),+0s,2299161j)>, :name=>"8"}]}