根据业务年份的“:date”值对哈希数组进行分组

Group a array of hash according to their `:date` value by business year

我有一个散列数组,每个散列中有 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"},
       ]

我想按营业年度对哈希进行分组,换句话说,四月到明年三月,如下所示:

[
 [{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更简洁

这个函数怎么写?

你可以使用 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"}]}