搜索对象数组,以使用不同的比较运算符匹配可能的多个值

时间:2010-05-14 01:04:43

标签: perl search arrays comparison operators

我有一个函数来使用eq运算符搜索对象数组中的匹配值,如下所示:

sub find {
    my ( $self, %params ) = @_;
    my @entries = @{ $self->{_entries} };

    if ( $params{filename} ) {
        @entries = grep { $_->filename eq $params{filename} } @entries;
    }
    if ( $params{date} ) {
        @entries = grep { $_->date eq $params{date} } @entries;
    }
    if ( $params{title} ) {
        @entries = grep { $_->title eq $params{title} } @entries;
    }
    ....

我还希望能够传入一个qr引用变量来代替比较,但我能想到分离比较的唯一方法就是使用if / else块,如下所示:

if (lc ref($params{whatever}) eq 'regexp') {
    #use =~
} else {
    #use eq
}

有更短的方法吗?由于我无法控制的原因,我使用的是Perl 5.8.8,因此无法使用智能匹配运算符。

TIA

2 个答案:

答案 0 :(得分:5)

这是Perl,所以当然有一个CPAN模块:Match::Smart。它与Perl 5.10的智能匹配运算符非常相似,只有您键入smart_match($a, $b)而不是$a ~~ $b

您可能希望与perlsyn documentation for 5.10 smartmatching进行比较,因为Match :: Smart可以处理更多情况。

否则,我没有看到任何错误:

sub smart_match {
    my ($target, $param) = @_;
    if (ref $param eq 'Regexp') {
        return ($target =~ qr/$param/);
    }
    else {
        return ($target eq $param);
    }
}

@entries = grep { smart_match($_->date, $params{date}) } @entries;

答案 1 :(得分:0)

我不确切地知道你想要的最终结果,但你可以这样做:

for my $field (qw(filename date title)) {
  my $p = $param($field};
  @entries = (ref($p) eq 'regexp')
    ? grep { $_->$field =~ /$p/ } @entries
    : grep { $_->$field eq $p }   @entries;
}

或者,您甚至可以将“eq”比较转换为正则表达式,例如:

my $entry = "string to be equal to";
my $re = qr/^\Q$entry\E/;

这简化了for循环中的逻辑。