I’m trying to filter an array of terms using another array in Perl. I have Perl 5.18.2 on OS X, though the behavior is the same if I use 5.010
. Here’s my basic setup:
#!/usr/bin/perl
#use strict;
my @terms = ('alpha','beta test','gamma','delta quadrant','epsilon',
'zeta','eta','theta chi','one iota','kappa');
my @filters = ('beta','gamma','epsilon','iota');
foreach $filter (@filters) {
for my $ind (0 .. $#terms) {
if (grep { /$filter/ } $terms[$ind]) {
splice @terms,$ind,1;
}
}
}
This works to pull out the lines that match the various search terms, but the array length doesn’t change. If I write out the resulting @terms
array, I get:
[alpha]
[delta quadrant]
[zeta]
[eta]
[theta chi]
[kappa]
[]
[]
[]
[]
As you might expect from that, printing scalar(@terms)
gets a result of 10
.
What I want is a resulting array of length 6, without the four blank items at the end. How do I get that result? And why isn’t the array shrinking, given that the perldoc page about splice
says, “The array grows or shrinks as necessary.”?
(I’m not very fluent in Perl, so if you’re thinking “Why don’t you just...?”, it’s almost certainly because I don’t know about it or didn’t understand it when I heard about it.)
You can always regenerate the array minus things you don't want. grep
acts as a filter allowing you to decide which elements you want and which you don't:
#!/usr/bin/perl
use strict;
my @terms = ('alpha','beta test','gamma','delta quadrant','epsilon',
'zeta','eta','theta chi','one iota','kappa');
my @filters = ('beta','gamma','epsilon','iota');
my %filter_exclusion = map { $_ => 1 } @filters;
my @filtered = grep { !$filter_exclusion{$_} } @terms;
print join(',', @filtered) . "\n";
It's pretty easy if you have a simple structure like %filter_exclusion
on hand.
Update: If you want to allow arbitrary substring matches:
my $filter_exclusion = join '|', map quotemeta, @filters;
my @filtered = grep { !/$filter_exclusion/ } @terms;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With