【问题标题】:Perl: Matching hash keys to a regular expressionPerl:将哈希键与正则表达式匹配
【发布时间】:2011-07-08 03:10:43
【问题描述】:

我想知道 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$/};

【问题讨论】:

  • 如果你有teen$ .* 是多余的。

标签: perl hash


【解决方案1】:

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;

【讨论】:

  • 请注意,此运算符一直处于不断变化的状态,并且自 Perl 5.18 起已被视为“实验性”(在任何使用它的地方都会发出警告)。 stackoverflow.com/questions/16927024/…
【解决方案2】:

除了这里的其他答案,您还可以使用 perl 的 grep 来做到这一点:

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

【讨论】:

    【解决方案3】:

    是的,它叫:

    use List::Util qw<first>;
    
    # Your regex does not compile perhaps you mean /teen$/
    my $value = $hash{ ( first { m/teen/ } keys %hash ) || '' };
    

    (即在智能匹配之前。请参阅 mob 的智能匹配答案。)

    您还可以对键进行排序:

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

    【讨论】:

    • sort?诶?如果您只是测试是否存在匹配项,则没有理由对键进行排序。 first { m/teen$/ } keys %hash 更好。
    • @Dave Sherohman:与 SO 中的往常一样,存在一般性问题,并且存在用户正在寻找的特定应用程序。一般问题是“将哈希键与正则表达式匹配”。 firstany 概念的实现——但包含其他含义:首先如何?我倾向于涵盖比特定应用程序更多的内容。
    • 我没有看到 任何 种情况,其中排序适用于“是否有匹配项?”的问题。匹配是否存在与顺序无关,因此顺序无关紧要。排序的唯一作用是强加一个特定的顺序,但顺序无关紧要,所以排序只是毫无目的地消耗资源(时间/内存)。这里的问题是询问any 的概念,与顺序无关; first 之所以合适,仅仅是因为 List::Util 不提供 any 函数。
    【解决方案4】:

    没有内置方式,但 CPAN 上有 Tie::Hash::Regex

    【讨论】:

      猜你喜欢
      • 2012-04-13
      • 2013-01-04
      • 2016-02-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-05
      • 1970-01-01
      • 1970-01-01
      • 2020-02-19
      相关资源
      最近更新 更多