Ruby组按月和年份分组

Jan*_*Jan 1 ruby activerecord

我有一个(ar)类PressClipping,包括标题和日期字段.

我必须像那样显示它:

2011年2月
title1
title2
...
2011年1月
......

执行此分组的最简单方法是什么?

Phr*_*ogz 6

这里有一些Haml输出显示如何使用迭代Enumerable#group_by:

- @clippings_by_date.group_by{|c| c.date.strftime "%Y %b" }.each do |date_str,cs|
  %h2.date= date_str
  %ul.clippings
    - cs.each do |clipping|
      %li <a href="...">#{clipping.title}</a>
Run Code Online (Sandbox Code Playgroud)

这将为您提供一个哈希,其中每个键都是格式化的日期字符串,每个值都是该日期的剪辑数组.这假设是Ruby 1.9,其中Hashes以插入顺序保留和迭代.如果你的体重低于1.8.x,你需要做的事情如下:

- last_year_month = nil
- @clippings_by_date.each do |clipping|
  - year_month = [ clipping.date.year, clipping.date.month ]
  - if year_month != last_year_month
    - last_year_month = year_month
    %h2.date= clipping.date.strftime '%Y %b'
  %p.clipping <a href="...>#{clipping.title}</a>
Run Code Online (Sandbox Code Playgroud)

我想你可以利用group_by1.8以下的优势(现在只使用纯Ruby来解决问题):

by_yearmonth = @clippings_by_date.group_by{ |c| [c.date.year,c.date.month] }
by_yearmonth.keys.sort.each do |yearmonth|
  clippings_this_month = by_yearmonth[yearmonth]
  # Generate the month string just once and output it
  clippings_this_month.each do |clipping|
    # Output the clipping
  end 
end
Run Code Online (Sandbox Code Playgroud)