Eric LIn
5/29/2008 6:34:00 PM
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 <stefano.cro...@alice.it> 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; i<RARRAY(ary)->len; 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