On 10/25/06, Paul Battley <pbattley / gmail.com> wrote:
> On 25/10/06, anthony.green / bbc.co.uk <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/