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