EchoAngel has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks, I have this array of elements and I would go foreach of each element about 4 times currently. But each time i go through the foreach loop, i find elements i want to remove from the array. So as I continue, the foreach loop should get smaller in elements. How can I do this?
  • Comment on Question Regarding remove elements from a list

Replies are listed 'Best First'.
Re: Question Regarding remove elements from a list
by si_lence (Deacon) on Aug 26, 2004 at 12:44 UTC
    You could use grep to remove the elements you do not want from the list:
    my @results = grep $expression, @input_list;

    The expression will be evaluated for each element in the @imput_list (put into $_) and only the element where the experssion evaluates to true end up in @result.
    hth
    si_lence
Re: Question Regarding remove elements from a list
by hardburn (Abbot) on Aug 26, 2004 at 12:46 UTC

    Hard to say without seeing your actual data, but it sounds like you want to use grep to filter out the data before the foreach loop:

    my @new_data = grep { $_ eq 'good data' } @old_data;

    Just change the block to run the tests on each element of the data. See the grep documentation for details.

    "There is no shame in being self-taught, only in not trying to learn in the first place." -- Atrus, Myst: The Book of D'ni.

Re: Question Regarding remove elements from a list
by keszler (Priest) on Aug 26, 2004 at 15:20 UTC
    If each existing foreach removes more elements than it keeps, the order is not sorted, and memory is not an issue, then

    my @tmp; while (my $elem = pop @array) { # or s/pop/shift/ # do stuff if ($keep) { push @tmp, $elem; } } @array = @tmp;
    Another method is to use an array index instead of foreach, and splice:
    my $i=0; while ($i < @array) { if (keep($array[$i]) { print "keeping $array[$i]\n"; $i++; } else { my $x = splice(@array,$i,1); print "discarding $x\n"; } }
Re: Question Regarding remove elements from a list
by johnnywang (Priest) on Aug 26, 2004 at 17:44 UTC
    If your logic for examning each element is a little complicated, I'll turn the array into a hash, and delete the key in each pass, something like:
    my %hash = map{$_=>undef} @inputs; foreach my $k (keys %hash){ # do something delete $hash{$k} if $do_not_keep; } # then do this loop again...
Re: Question Regarding remove elements from a list
by Forsaken (Friar) on Aug 27, 2004 at 07:57 UTC
    perhaps a less simple solution than using ie grep, but how about embedding the foreach in a for loop? during the foreach keep track of all items that are to be removed at the end of that foreach loop, ie in a separate array, and before the next instance of the for loop simply cut out the slices using (number of slice - number of items already removed in that instance of the for loop).