I have an array as below :
my @arr = qw (ram sam ham dam yam fam lam cam)
I want to remove sam
, yam
and lam
from the above array using splice
.
I am using below code to do it :
# first getting the index of sam
(my $ind ) = grep {$arr[$_] eq 'sam'} 0 .. $#arr;
splice(@arr, $ind, 1);
My question is since the array elements have changed their position, I need to again fetch the index of yam
and lam
and do a splice on the array.
Is there any other way so that in one-go I will remove the random elements from the array using splice. I can get the index of all of them in once and delete them from the array but those positions will hold undef value which I do not want.
If you know the values of elements to remove (sam
etc in this case), and not indices, can do
my $re = join '|', map { q(^) . quotemeta . q(\z) } qw(sam yam lam);
my @filtered_ary = grep { not /$re/ } @ary;
or, really
my $re = join '|', map { quotemeta } qw(sam yam lam);
$re = qr/^(?:$re)\z/;
my @filtered_ary = grep { not /$re/ } @ary;
Can also overwrite the array
@ary = grep { ... } @ary
See quotemeta which escapes "all ASCII non-"word" characters" so that characters with a special meaning in a regex can be used as literal characters, and qr, building a regex. The use of qr
is most of the time not necessary but I consider it good practice.
No need to first find the index in order to use splice
(and which you'd have to use repeatedly for all non-contiguous indices).
Or, as in jhnc
comment
my %remove = map { $_ => 1 } qw(sam yam lam);
@ary = grep { not $remove{$_} } @ary;
This is quicker than the solution above as it only does a lookup instead of a regex, while their overhead is fairly similar.