On 2006.01.29 07:05, Jonathan Leighton wrote:
> Hi,
> 
> I'm going ever so slightly crazy over some looping behaviour. Here's a
> simplified test case I made:

I am feeling really dense today so I may be totally off mark, but...

> ----
> def categorise(items)
>   categorised = []
>   add = proc { |item| categorised << { :num => item[:num], :items => [ item[:foo] ] } }
> 
>   items.each do |item|
>     if categorised.empty?
>       add.call(item)

This is only done once, because categorised will no longer be empty.

>     else
>       categorised.each do |cat|

cat is the first and last element of categorised.

>         if cat[:num] == item[:num]
>           cat[:items] << item[:foo]
>           break
>         elsif cat == categorised.last

This will be true.

>           add.call(item)
>           break
>         end
>       end
>     end
>   end
>   
>   categorised
> end
> 
> p categorise( [ { :num => 1, :foo => 'foo1' }, { :num => 45, :foo => 'foo45' } ] )
> p categorise( [ { :num => 1, :foo => 'foo1' }, { :num => 45, :foo => 'foo45' }, { :num => 1, :foo => 'foo1' } ] )
> ----
> 
> Which produces:
> 
> [{:num=>1, :items=>["foo1"]}, {:num=>45, :items=>["foo45"]}]
> [{:num=>1, :items=>["foo1", "foo1"]}, {:num=>45, :items=>["foo45"]}]
> 
> Good-oh.
> 
> HOWEVER, if I remove the breaks from the categorised loop, it produces
> all sorts of spectacular results (try it yourself). This I cannot
> understand:
> 
>  * For the first one, if cat[:num] == item[:num], this implies that
> there are no other instances of this particular number. Which of course
> is what I want. The break perhaps speeds things up because it doesn't
> have to iterate more than needed, but it shouldn't affect the end result
> as far as I can see.
>  * For the second one, it should only be run if cat == categorised.last,
> ie we're on the last item in the array. Which means that the iteration
> should not be run again. So why does the break affect things?
> 
> I'm really getting quite confused about this so I'd be really glad of an
> explanation.
> 
> Thanks a lot
> 
> Jonathan Leighton


E