in reply to What's the idiom for finding and removing the found @ARRAY element?

If you absolutely must modify an array in place with deletes, then you could do it this way:
for my $i ( reverse 0 .. $#a ) { splice( @a, $i, 1 ) if should_delete; }
The point being that each time you delete an element, the indices of all elements after it in the array change.
As an exercise, consider what the above code would do if the reverse were removed.

Replies are listed 'Best First'.
(tye)Re: What's the idiom for finding and removing the found @ARRAY element?
by tye (Sage) on Nov 06, 2002 at 16:41 UTC

    For some cases, it will be faster to not move all of the elements down each time:

    my $o= 0; for my $i ( 0..$#$av ) { if( should_keep($i) ) { $av->[$o++]= $av->[$i]; } } $#$av= $o-1;

            - tye
      As far as that goes, it might be more efficient, in some cases, to not change the length of the array at all, and just set the "undesirable" elements to undef. Then, later, when the array is processed, just skip over the undef ones.
Re: Re: What's the idiom for finding and removing the found @ARRAY element?
by John M. Dlugosz (Monsignor) on Nov 06, 2002 at 04:32 UTC
    Good point about the reverse, if I was removing more than one. That's what I'm doing, but returning out of the loop as soon as I found it.

    Now, can you apply the $# syntax to a reference? My brain gagged at that, even if Perl wouldn't (I went with scalar -1).

      my $arr = [(1) x 5]; print $#$arr;

      Makeshifts last the longest.

      Sure, that's what curly braces are for. (Well, one of the many things.)
      for my $i ( reverse 0 .. $#{ $ar } ) { splice @{ $ar }, 0, $i; }
Re: Re: What's the idiom for finding and removing the found @ARRAY element?
by rir (Vicar) on Nov 06, 2002 at 14:49 UTC
    If you absolutely must modify an array in place with deletes, then you could do it this way:

    for my $i ( reverse 0 .. $#a ) { splice( @a, $i, 1 ) if should_delete; }

    You could but I wouldn't recommend it. Count down in a while loop.

    Normally when I feel the need to alter an array in place, I won't want to create the lists  0 through  $#a and  $#a through  0.

    The new foreach optimization of the range operator would be much more useful if the behaviour of $#a .. 0 had not changed. Oh well.