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

Perl中确定字符串变量是否与列表中的字符串匹配的惯用方法是什么?,perl,list,hash,Perl,List,Hash,规范的一部分说:“有些名字是特殊的,例如Hughie、Dewey、Louis和Donald。在项目的整个生命周期中,可以在任意时间添加其他名字。每当您输入其中一个名字时,请使用quack.wav。” 我可以写 while (<>) { if ($_ =~ /Hughie|Dewey|Louis/) { quack() ; } elsif ($_ =~ /Donald/ { quack() ; you_re_fir

规范的一部分说:“有些名字是特殊的,例如Hughie、Dewey、Louis和Donald。在项目的整个生命周期中,可以在任意时间添加其他名字。每当您输入其中一个名字时,请使用quack.wav。”

我可以写

while (<>) {
    if ($_ =~ /Hughie|Dewey|Louis/) {
        quack() ;
    }
    elsif ($_ =~ /Donald/ {
        quack() ;
        you_re_fired_apprentice() ; # Easter egg don't tell QA
    }
}
while(){
如果($|=~/Hughie | Dewey | Louis/){
庸医();
}
elsif($\ux=~/Donald/{
庸医();
你被炒鱿鱼了复活节彩蛋别告诉QA
}
}
…但是,尽管要进行解构以实现,但它看起来是WTF-y:二进制搜索在哪里?如果鸭子名字的数量突然大幅增加怎么办?它根本无法扩展

我可以在临时目录中使用这些名称创建空文件,然后使用“file exists”API,但这似乎有些迂回,我必须确保它们最终被删除

当然有更好的方法吗?

您可以使用。另请参见和


使用散列来实现一个集合并不是很好,但应该很快。

如果你想使用数组而不是散列,你可以使用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
    }
}
@specialnames=qw(休吉·杜威·路易斯);
而(我的$value=){
if(grep{$value-eq$\},@specialnames){
庸医();
}
elsif($\ux=~/Donald/{
庸医();
你被炒鱿鱼了复活节彩蛋别告诉QA
}
}

这比散列的伸缩性要差得多,甚至可能比将数组复制到散列中然后进行散列查找的伸缩性更差。

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

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
    }
}
my%ducks=map{$\=>1}qw(休吉·杜威·路易斯);
而(){
如果($ducks{$}){
庸医();
}
elsif($eq'Donald'){
庸医();
你被炒鱿鱼了复活节彩蛋别告诉QA
}
}
创建散列需要一点时间,但不会超过
O(n)
。但是,使用散列进行查找是
O(1)
,因此它比顺序搜索(通过grep或带有替代项的正则表达式)更有效,假设您要检查一个或两个以上的项


顺便说一句,您拥有的正则表达式将匹配搜索字符串中的任何位置的单词。如果您想要精确匹配,您需要添加开始和结束锚。

如前所述,哈希是实现这一点的方法。这是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";
}

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


或者,您可以使用

这是所使用的,因此您可以编写

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

我最近(过去3周)得到了一个答案,因此详细分析了使用哪种列表搜索技术会出现什么情况。@DVK这一个-->?使用哈希实现(而不是“模拟”)一个集合数据类型在其表现力上既非常自然,又相当干净。@tchrist:“不完全漂亮”指的是虚拟值的必要性,与Python中用户看不到虚拟值的集合相比。耶!我很害怕[sic]没有人会提到
~
。不过,你还是回到了O(N)。顺便说一句,这不应该是
你被解雇了\u学徒()
?☺是的,如果没有别的,这似乎是最简洁的答案。除了巴甫洛夫式的回答,“in”通常也可以拼写为“~~”。搜索引擎不愿意为~~操作符报告结果。简洁的答案是+1。智能匹配现在是我Perl实用工具带中的一个新工具,谢谢。“in”?你说“in”?每当你发现自己在使用usi时比如in,once,first,unique,union,intersection,set,record,struct,union,或者其他一些不相关的词,你应该会有一个瞬间的,下意识的,巴甫洛夫式的反应,一个尤里卡灯泡在你的脑袋里爆炸,喊着HASH!!我应该用HASH!!当然!!!永远不要相信任何写
$\u=~/什么的人ver/
.Ever.@tchrist:即使是默认群组,您也从未遇到过“始终指定-$\”?my@foo=();(以防万一)群组如何?我想匹配字符串中的任何位置。很明显,没有一种方法可以通过哈希实现这一点。
my @ducks = qw(Hughie Dewey Louis);
my $name = 'Dewey';

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