From: Jonathan Leighton Date: 2006-01-29T07:05:38+09:00 Subject: Loop weirdness Hi, I'm going ever so slightly crazy over some looping behaviour. Here's a simplified test case I made: ---- def categorise(items) categorised = [] add = proc { |item| categorised << { :num => item[:num], :items => [ item[:foo] ] } } items.each do |item| if categorised.empty? add.call(item) else categorised.each do |cat| if cat[:num] == item[:num] cat[:items] << item[:foo] break elsif cat == categorised.last 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 http://turnipspatch.com/ | http://jonathanleighton.com/ | http://digital-proof.org/