Reputation: 233
I need to filter a hash based on a regex, deleting the keys from the hash if the regex matches.
This is what i got so far, unfortunately it doesnt do anything and i have no clue why.
So, i am building the regex out of an array of strings, i need to match substrings as well, so if the hash key is someprefix_somestring
i need to match it against somestring
or string
my $hashref = {someprefix_somekey => 'somevalue', otherprefix_otherkey => 23, otherprefix_somekey => 'someothervalue'};
my @array_of_strings = ('somekey', 'strings', 'bits', 'bobs');
my $regex = join( '|', sort { length( $b ) <=> length( $a ) or $a cmp $b } @array_of_strings );
$regex = qr{($regex)};
delete $hashref->{ grep { !m/$regex/ } keys %$hashref };
I would expect $hashref
to look like this afterwards: {otherprefix_otherkey => 23}
since someprefix_somekey
and otherprefix_somekey
would have matched $regex
and would therefore be deleted from the hash
I have no clue why this is not working, please enlighten me
Thanks to hobbs answer i was able to make it work, this is what i have now:
my $hashref = {someprefix_somekey => 'somevalue', otherprefix_otherkey => 23, otherprefix_somekey => 'someothervalue'};
my @array_of_strings = ('somekey', 'strings', 'bits', 'bobs');
my $regex = join( '|', sort { length( $b ) <=> length( $a ) or $a cmp $b } @array_of_strings );
$regex = qr{($regex)};
delete @{$hashref}{grep { m/$regex/ } keys %$hashref };
Upvotes: 3
Views: 2198
Reputation: 240414
Your delete
isn't quite right because you're using the notation to access a single key, therefore the grep
is run in scalar context. Which means that ultimately you're trying to do something like delete $hashref->{'3'}
if there are three keys not matching your regex.
If you change your last line to this it should work:
delete @{$hashref}{grep /$regex/, keys %$hashref };
which uses a hash slice. If you think that syntax is too ugly, you could also
delete $hashref->{$_} for grep /$regex/, keys %$hashref;
which might read a little bit more naturally.
Upvotes: 7