```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?

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.

>           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?
>