in reply to How can I delete an element in a foreach cycle?

Is there a particular need to do this in a foreach loop and in place? For example, this would seem to me to be a textbook example of when to use grep:

@array = qw(hi hello howdy); @array = grep {!/^hello$/} @array; print join "\n", @array;

If you need to do this in the context of a loop, perhaps it would make sense to combine loop control with undef and filtering after the loop:

@array = qw(hi hello howdy); for (@array) { if ($_ eq 'hello') { undef $_; next; } # Process list elements } @array = grep {defined} @array; print join "\n", @array;

Replies are listed 'Best First'.
Re^2: How can I delete an element in a foreach cycle?
by JavaFan (Canon) on Feb 26, 2010 at 23:31 UTC
    That would filter out any elements that were undefined to begin with. Another solution:
    my @keep; for (my $i = 0; $i < @array; $i++) { my $_ = $array[$i]; push @keep, $i unless $_ eq 'hello'; } @array = @array[@keep];
    Or:
    for (my $i = @array; $i--;) { splice @array, $i, 1 if $array[$i] eq 'hello'; }
    But splice can be expensive; don't use that when deleting lots of things from a huge array.

      It's never a good idea to mess with the JavaFan, but would either of those approaches be faster or more straightforward than, or in any way preferable to something like (assuming the array may contain undefined elements):

      >perl -wMstrict -le "my @array = (qw(hi hiya hello hello), undef, qw(lo hello)); @array = grep !defined || $_ ne 'hello', @array; print defined($_) ? qq{'$_'} : 'UNDEF' for @array; " 'hi' 'hiya' UNDEF 'lo'
        The JavaFan code works for sure, but it looks like c/c++ way: incrementing a number, you've got the index reference... but it doesn't appear too pearlish. There is a way to do it in a more perlish way? AnomalousMonk, I don't understand perfectly your code. You see, I'm only a novice. Please, Can you do a better explains?
        Well, the question was how to delete from a foreach cycle; a grep isn't one. I presumed the "delete if equal to a specific value" was an example. I prefer
        foreach (...) { multiple lines of statements }
        over
        @array = grep { multiple lines of statements } @array;
        ok, thank you all for your answers. I like that way: to mark the element as "undef" in foreach cycle and then delete it throught a grep. I understood also the lesson of JavaFan: "there is more than one way to do it". But I'm also searching a way for me. That way must be a little different from the way I usually know (like the construct similar to C/C++), just because from my personal point of view (this is only my vision) I'm using perl just to have shorcuts where other programming languages are using explict constructs. These shortcuts for me are the funny part of perl. Thank you for all the answers.

        Anomalous Monk, the reason I used "throught" is that I'm not a "natural English speraker"... so my thoughts maybe inaccurate in English...

        ...and yes, I can use grep at all, instead of use a foreach, and then a grep.

        Thank you for your answers!