tags:

views:

117

answers:

2

I have an Array of Events and I want to divide them into a 2-dimensional Array based on event_date (which returns a Time object). But I want it to be by the day part of the date. Here's what I have so far:

def divide_events_by_day(events)
  # Sort, so we can start with the first day.
  events = events.sort { |x,y| x.event_date <=> y.event_date }
  days = []
  current_date = events[0].event_date # A Time object.
                                      # With meaningful hours and minutes.
  while events.length > 0 do
    # Find events for the current date.
    day_events = events.select { |e|
      (e.event_date.year == current_date.year) && 
        (e.event_date.yday == current_date.yday)
    }
    # Move them to their subarray.
    days << day_events
    events = events - day_events

    # Advance the current_date by one day.
    current_date = (current_date + (60 * 60 * 24))
  end
  days
end

Any suggestions to make it simpler or faster?

+1  A: 

This should be faster:

def divide(events)
  hash = {}
  events.each do |event| 
    key = "#{event.event_date.year} #{event.event_date.yday}" 
    hash[key] ||= []
    hash[key] << event
  end
  hash.to_a.sort do|pair1,pair2| 
    pair1[0] <=> pair2[0]
  end.map do |pair| 
    pair[1].sort{|x,y| x.event_date <=> y.event_date}
  end
end
Sam Saffron
+2  A: 

For a start, you could try something like this:

def divide_events_by_day(events)
    days = [[]]
    events.sort_by { |x| x.event_date }.each { |e| 
        if days.last.empty? or days.last.event_date_date == e.event_date.date
            days.last << e
          else
            days << [e]
          end
        }
    days
    end

It doesn't produce empty days, but other than that follows yours pretty closely.

I have a Time#date method on my machine, but I'm not seeing it in a clean distribution build (1.8.7), so you may need to add something like:

class Time
    def date
        to_i/(60*60*24)
        end
    end
MarkusQ
better approach than mine, should be == , also dont you need to add code to breakdown by day of year ...
Sam Saffron
Date Time#date is just the whole-date part. Hmmm. It's not in pickaxe, but it works for me. I wonder if it's part of some extension I've got loaded, or standard but newer than my dead tree book...
MarkusQ
MarkusQ
Thanks for the help. It's a good solution. I think "days.last.event_date_date" should be "days.last.last.event_date.date".
Ethan