From: ericlin852@... Date: 2008-05-30T03:34:59+09:00 Subject: Re: Mysterious behavior with loops Thanks Stefano, that definitely answered my question. It's quite obvious when the index variable is made explicit. Eric On May 29, 10:16 am, Stefano Crocco wrote: > On Thursday 29 May 2008, ericlin...@gmail.com wrote: > > > > > Enter these in irb: > > > a = [1,2,3] > > > a.each do |i| > >   a.delete(i) > > end > > > Result? > > > a => [2] > > > Shouldn't a be [] ? > > > Eric > > Iterating on an array while deleting elements from it is usually a bad idea, > because items may be skipped, as it happens in your case. In particular, this > is the C code for Array#each: > > VALUE > rb_ary_each(ary) > VALUE ary; > { >   long i; >   for (i=0; ilen; i++) { >     rb_yield(RARRAY(ary)->ptr[i]); >   } >   return ary; > > } > > If you don't understand C code, this is what it means: for all the numbers > from 0 to the number of elements in the array (excluded), take the element of > the array with that index and pass it to the block. > > Now, look what happens for the first element of the array. The index is 0, > corresponding to the element 1. The element is passed to the block, which > deletes it. Now, the array contains only two elements: 2 and 3, with 2 > corresponding to the index 0 and 3 to the index 1. But the index used by each > to iterate on the array elements is increased to 1 (since Array#each can't > know that you deleted an item). This means that the next element which will be > passed to the block will be the one corresponding to index 1, which is 3. This > means that one item won't be passed to the block and won't be deleted. > > If you want to delete all items of the arryay, you can simply use the delete > method. If you want to delete only some items, you can use Array#delete_if, > which takes a block and removes from the array all the elements for which the > block returns true. > > I hope this helps > > Stefano