From: Rick DeNatale Date: 2006-10-26T00:07:00+09:00 Subject: Re: Reopening Classes On 10/25/06, Paul Battley wrote: > On 25/10/06, anthony.green@bbc.co.uk wrote: > > > > Can someone offer an explaination as to what I'm encountering here.. > > Range#each employs <=>, so by changing the semantics of the > comparison, you break your step loop. When you redefine <=> after the > loop, it doesn't affect it, so your second example works. > > Instead of altering Time, you could just do this: > > time_slots.sort_by{ |ts| ts.strftime("%H%M%S%Y%m%d").to_i } Another observation. Building a range of times and then using step to obtain each hour is pretty inefficient. Range#step basically works like this I might have an off by one bug but it gets the idea across: class Range def step(incr = 1) elt = self.begin end = self.end ctr = 0 while ((elt <=> end) if (ctr == 0) yield elt ctr = incr end elt = elt.succ ctr -= 1 end end And Time#succ gives the time one second later than the receiver. So the while look is going to be executed once for every second in the range, in this case 6 days * 24 hours * 60 minutes * 60 seconds, so to get the 144 Time objects actually needed, a total of 518400 will be allocated. This costs time and memory, and GC cycles, which may or may not be important. Another way to compute timeslots which avoids this might be: timeslots = (0..6*24).map {|h| first + h.hour} Generalizing this to arbitray start and end times is left as an exercise to the reader. -- Rick DeNatale My blog on Ruby http://talklikeaduck.denhaven2.com/