2011-03-03 18 views
18

Perl'in belirli bir düzenli ifadeyle eşleşen bir anahtar ile bir hash öğesi olup olmadığını kontrol etmek için yerleşik bir yolu olup olmadığını merak ediyorum. Örneğin: Bunu yapmak için herhangi bir yolu varsaPerl: Karma anahtarların düzenli bir ifadeyle eşleştirilmesi

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

merak ediyorum:

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

Eğer 'teen $' varsa ''. * 'Gereksizdir. – Axeman

cevap

24

smart match operator bunu yapar (Perl v5.10'dan itibaren kullanılabilir).

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

Örnek kullanım:

# print if any key in %h ends in "teen" 
print "We have some teens\n" if /.*teen$/ ~~ %h; 
+1

Bu operatörün bir akı durumunda olduğunu ve Perl 5.18'den itibaren “deneysel” olarak kabul edildiğini unutmayın (kullanıldığı her yerde uyarıları yayar). http://stackoverflow.com/questions/16927024/perl-5-20-and-the-fate-of-smartmatch-and-given-when/ – sundar

+1

Her şey yolunda. – user1807271

6

Evet, deniyor:

use List::Util qw<first>; 

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

(akıllı maç öncesinde, yani akıllı maç için mob.un yanıta bakın..)

You ayrıca şu anahtarları da sıralayabilir:

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

Bir "operasyonu" içine bu donduracak:

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 }; 
    } 
} 

Ve bunu gibi kullanabilirsiniz: diğer cevaplar ek olarak

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

Ya

my $key = values_for_keys_like($base->{level_two}{level_three} => qr/teen/); 
+0

'sort'? Eh? Bir eşleşmenin olup olmadığını test ederseniz anahtarları sıralamak için bir neden yoktur. Sadece 'ilk {m/teen $ /} tuşları% hash' daha iyidir. –

+0

@Dave Sherohman: Her zamanki gibi, genel bir soru var ve kullanıcının aradığı özel uygulama var. Genel soru şudur: "Sıralı ifadeleri düzenli ifadeyle eşleştirme". '' '' '' '' '' '' '' '' '' '' '' herhangi bir kavram '' uygulamasıdır - ancak diğer sonuçları içerir: ilk * nasıl? * Belirli bir uygulamadan daha fazlasını kapsamayı severim. – Axeman

+2

"Herhangi bir eşleşme var mı?" Sorusuna uygulanabilecek herhangi bir * durumu göremiyorum. Bir eşleşmenin var olup olmadığı, düzenden bağımsız olup, siparişin önemi yoktur. Sıralamanın tek etkisi, belirli bir düzen empoze etmektir, ancak sıralamanın önemi yoktur, bu yüzden sıralama, hiçbir amaç için yalnızca kaynakları (zaman/bellek) kullanır. Buradaki soru, düzenden bağımsız, “herhangi” kavramını sormaktır; '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' –

12

Burada ayrıca perl'in grep'i ile de yapabilirsiniz:

print "We have some teens\n" if grep {/.*teen/} keys %h; 
İlgili konular