在Perl中确定字符串变量是否与列表中的字符串匹配的惯用方法是什么?

时间:2011-01-31 22:18:18

标签: perl list hash

规范的一部分说“有些名字很特别,例如Hughie,Dewey,Louis和Donald。在项目的整个生命周期中,可以随意添加其他名称。每当你输入其中一个名字时,玩嘎嘎。 WAV“。

可以写...

while (<>) {
    if ($_ =~ /Hughie|Dewey|Louis/) {
        quack() ;
    }
    elsif ($_ =~ /Donald/ {
        quack() ;
        you_re_fired_apprentice() ; # Easter egg don't tell QA
    }
}

...但是虽然要解除实施,但它看起来是WTF-y:二进制搜索在哪里?如果鸭子名字的数量突然大幅增加怎么办?它根本不会扩展!

我可以在临时目录中使用这些名称创建空文件,然后使用“文件存在”API,但这看起来很迂回,我必须确保它们最后被删除。

当然有更好的方法吗?

6 个答案:

答案 0 :(得分:7)

你可以这样写,但你应该这样写:

my %ducks = map {$_ => 1} qw(Hughie Dewey Louis);

while (<>) {
    if ($ducks{$_}) {
        quack() ;
    }
    elsif ($_ eq 'Donald') {
        quack() ;
        you_re_fired_apprentice() ; # Easter egg don't tell QA
    }
}

创建哈希需要一点时间,但不能超过O(n)。使用哈希的查找是O(1),因此它比顺序搜索(通过grep或带有替换的正则表达式)更有效,假设您将检查多于一个或两个项目。

顺便说一句,你拥有的正则表达式将与搜索字符串中的任何位置匹配。如果想要完全匹配,则需要添加起始锚点和结束锚点。

答案 1 :(得分:7)

或者,您可以使用smart matching

my @ducks = qw(Hughie Dewey Louis);
my $name = 'Dewey';

say 'smart match' if $name ~~ @ducks;

这是switch statements使用的内容,因此您可以编写

given ($name) {
    when (@ducks) {
        quack();
    }
    when ('Donald') {
        quack();
        you_re_fired_apprentice(); # Easter egg don't tell QA
    }
}

答案 2 :(得分:4)

如前所述,哈希是实现这一目标的方法。这是OOP之前OOP的样子。

use strict;
use warnings;

my %duck_action = (
  Donald => sub {quack(); you_re_fired_apprentice()},
  Hughie => sub {quack()},
  Dewie  => sub {quack()},
  Louis  => sub {quack()},
);

for my $duck (qw( Hughie Dewie Donald Louis Porkie )) {
    print "$duck: ";
    my $action = $duck_action{$duck} || &no_such_duck;
    $action->();
}

sub quack {
    print "Quack!\n";
}

sub you_re_fired_apprentice {
    print "You're fired!\n";
}

sub no_such_duck {
    print "No such duck!\n";
}

答案 3 :(得分:3)

您可以使用Perl Hash。另请参阅How can I represent sets in Perl?Representing Sets in Perl

使用哈希来实现一个集合并不完全漂亮,但它应该快速

答案 4 :(得分:2)

要在列表中查找字符串,您还可以在List::MoreUtils中使用any

use List::MoreUtils qw(any);

my @ducks = qw(Hughie Dewey Louis);
my $name = 'Dewey';

say 'any' if any {$name eq $_} @ducks;

答案 5 :(得分:1)

如果您使用数组而不是散列,则可以使用perl的grep函数在数组中搜索字符串。

@specialnames = qw(Hughie Dewey Louis);
while (my $value = <>) {
    if (grep {$value eq $_}, @specialnames) {
        quack() ;
    }
    elsif ($_ =~ /Donald/ {
        quack() ;
        you_re_fired_apprentice() ; # Easter egg don't tell QA
    }
}

这确实比散列更糟糕,甚至可能比将数组复制到散列然后进行散列查找更糟糕。