use strict;
use warnings;
sub grep_in_place(&\@) {
my ($cb, $array) = @_;
my $src = -1;
my $dst = -1;
while (++$src < @$array) {
my $keep;
$keep = $cb->() for $array->[$src];
$array->[++$dst] = $array->[$src] if $keep;
}
$#$array = $dst;
}
my @a = (1,2,3,4,5,6,7,8);
print("Before: @a\n");
grep_in_place { $_ > 4 } @a;
print("After: @a\n");
####
Before: 1 2 3 4 5 6 7 8
After: 5 6 7 8
####
sub grep_and_remove(&\@) {
my ($cb, $array) = @_;
my $src = -1;
my $dst = -1;
my @deleted;
while (++$src < @$array) {
my $keep;
$keep = $cb->() for $array->[$src];
($keep
? $deleted[@deleted]
: $array->[++$dst]
) = $array->[$src];
}
$#$array = $dst;
return @deleted;
}
my @a = (1,2,3,4,5,6,7,8);
print("Before: @a\n");
my @b = grep_and_remove { $_ > 4 } @a;
print("After: @a\n");
print("Returned: @b\n");
####
Before: 1 2 3 4 5 6 7 8
After: 1 2 3 4
Returned: 5 6 7 8