2011-03-03 3 views
18

특정 정규 표현식과 일치하는 키를 가진 해시 요소의 존재를 확인하는 내장 된 방법이 있는지 궁금합니다. 예를 들어 :이 작업을 수행 할 수있는 방법이 있다면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$/}; 
+2

'십대 $'를 사용하면'. *'는 불필요합니다. – Axeman

답변

24

smart match operator (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; 
+1

이 연산자는 플럭스 상태 였고 Perl 5.18 (사용 된 곳에서는 경고가 표시됨)부터 "실험적"으로 간주되었습니다. http://stackoverflow.com/questions/16927024/perl-5-20-and-the-fate-of-smartmatch-and-given-when/ – sundar

+1

나를 위해 괜찮습니다. – user1807271

4

있다 어떠한 내장 방식으로,하지만 CPAN에 Tie::Hash::Regex이 있습니다.

6

그래,라고 :

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/); 
+0

'정렬 '? 뭐라고? 일치하는 항목이 있는지 테스트하는 경우에는 키를 정렬 할 필요가 없습니다. '첫 번째 {m/teen $ /} 키 % 해시'가 더 좋습니다. –

+0

@Dave Sherohman : 평소와 마찬가지로 일반적 질문이 있으며 사용자가 찾고자하는 특정 응용 프로그램이 있습니다. 일반적인 질문은 "해시 키를 정규 표현식과 일치시키는 것"입니다. 'first'는'any' 개념을 구현 한 것입니다. 그러나 다른 의미를 포함하고 있습니다 : first * how? * 나는 특정 어플리케이션보다 더 많이 다루는 경향이 있습니다. – Axeman

+2

정렬이 "일치합니까?"라는 질문에 적용 가능한 * 상황이 보이지 않습니다. 일치 여부는 주문과 무관하므로 주문이 부적합합니다. 정렬의 유일한 효과는 특정 순서를 부과하는 것이지만 순서는 부적절하므로 정렬은 아무런 목적없이 리소스 (시간/메모리)를 사용합니다. 여기에있는 질문은 질서와 무관 한 '모든'개념에 대해 묻고있다. 'first'는'List :: Util'이'any' 함수를 제공하지 않기 때문에 적절합니다. –

12

여기에도 perl의 grep을 사용하여 이것을 할 수 있습니다 :

print "We have some teens\n" if grep {/.*teen/} keys %h; 
관련 문제