Perl: сопоставление хеш-ключей с регулярным выражением - PullRequest
18 голосов
/ 03 марта 2011

Мне интересно, есть ли в Perl встроенный способ проверки существования хеш-элемента с ключом, соответствующим определенному регулярному выражению.Например:

my %h = ( 'twelve' => 12, 'thirteen' => 13, 'fourteen' => 14 );

Мне интересно, есть ли способ сделать это:

print "We have 12\n" if exists $h{twelve};
print "We have some teens\n" if exists $h{/.*teen$/};

Ответы [ 4 ]

24 голосов
/ 03 марта 2011

Оператор умного сопоставления делает это (доступно с Perl v5.10).

$a      $b        Type of Match Implied    Matching Code
======  =====     =====================    =============
...
Regex   Hash      hash key grep            grep /$a/, keys %$b
...

Пример использования:

# print if any key in %h ends in "teen"
print "We have some teens\n" if /.*teen$/ ~~ %h;
12 голосов
/ 03 марта 2011

В дополнение к другим ответам здесь вы также можете сделать это с помощью perl grep:

print "We have some teens\n" if grep {/.*teen/} keys %h;
6 голосов
/ 03 марта 2011

Да, это называется:

use List::Util qw<first>;

# Your regex does not compile perhaps you mean /teen$/
my $value = $hash{ ( first { m/teen/ } keys %hash ) || '' };

(То есть перед умным сопоставлением. См. Ответ моба для умного сопоставления.)

Вы также можете отсортировать ключи:

my $value = $hash{ ( first { m/teen/ } sort keys %hash ) || '' };

Я бы заморозил это как "операцию":

use Scalar::Util qw<reftype>;

sub values_for_keys_like (\[%$]$) {
    my $ref = reftype( $_[0] ) eq 'HASH' ? $_[0] : $$_[0];
    return unless my @keys = keys %$ref;

    my $regex = shift;
    # allow strings
    $regex    = qr/$regex/ unless my $typ = ref( $regex );
    # allow regex or just plain ol' filter functions.
    my $test  = $typ eq 'CODE' ? $regex : sub { return unless m/$regex/; 1 };

    if ( wantarray ) { 
        return unless my @k = grep { defined $test->( $_ ) } @keys;
        return @$ref{ @k };
    }
    else {
        return unless my $key = first { defined $test->( $_ ) } @keys;
        return $ref->{ $key };
    }
}

И вы можете использовать это так:

my $key = values_for_keys_like( %hash => qr/teen/ );

Или

my $key = values_for_keys_like( $base->{level_two}{level_three} => qr/teen/ );
4 голосов
/ 03 марта 2011

Нет встроенного способа, но на CPAN есть Tie::Hash::Regex.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...