Niko S P
Niko S P

Reputation: 233

perl - filter hash by keys matching regex without smartmatch

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

Answers (1)

hobbs
hobbs

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

Related Questions