I imagine there's a few million versions out there of the cull function I'm about to describe, but I couldn't find one in the obvious places (e.g. List::Util, List::MoreUtils, etc.), so here it goes.
The cull function faintly resembles grep. It takes as arguments two references, the first one to a sub, and the second one to an array. It returns all the elements of the array for which the sub evaluates to true, but, contrary to grep it has the side effect of removing these elements from the original array.
Example:
my @x = qw( eenie meenie minie moe );
my @y = cull { /m.*nie/ } @x;
print "@y\n";
print "@x\n";
__END__
meenie minie
eenie moe
Note that when invoked as shown, it is not necessary to include the
sub keyword nor to precede the array with
\.
As with grep and map, the sub passed as the argument to cull does not get its argument from $_[0], but rather it reads it from $_.
One important difference between cull and grep is that cull takes exactly two arguments: the first one must be a subref (or a code block, but not a boolean expression), and the second one must be an array. Hence, for example, the second statement below would result in an error:
my @x = grep { /m.*nie/ } qw( eenie meenie minie moe );
my @y = cull { /m.*nie/ } qw( eenie meenie minie moe );
Of course, these are OK too:
my @y = cull sub { /m.*nie/ }, @x;
my @y = cull( sub { /m.*nie/ }, @x );
As always, I look forward to reading your comments and suggestions.
Update: the point in the comments about the unnecessary expansion of the array indices is a good one, so I changed the original line
for my $i ( reverse 0 .. $#$array ) {
as suggested. Thanks.