我正在寻找列表中元素的存在.
在Python中有一个in关键字,我会做类似的事情:
if element in list:
doTask
Run Code Online (Sandbox Code Playgroud)
在Perl中是否有类似的东西而不必手动遍历整个列表?
Bra*_*ert 110
在v5.10.0中添加并在v5.10.1中进行了重大修订的智能匹配一直是一个常见的投诉点.尽管有许多方法可用,但它也证明了Perl的用户和实现者都存在问题和困惑.关于如何最好地解决问题,已经提出了许多建议.很明显,smartmatch几乎肯定会在将来改变或消失.不建议依赖其当前行为.
现在,当解析器看到〜,给定或何时发出警告.
该智能匹配~~操作.
if( $element ~~ @list ){ ... }
if( $element ~~ [ 1, 2, 3 ] ){ ... }
Run Code Online (Sandbox Code Playgroud)你也可以使用given/when construct.其中内部使用智能匹配功能.
given( $element ){
when( @list ){ ... }
}
Run Code Online (Sandbox Code Playgroud)您还可以将for循环用作"局部化器"(意思是它设置$_).
for( @elements ){
when( @list ){ ... }
}
Run Code Online (Sandbox Code Playgroud)Perl 5.12中出现的一件事是使用后修复版本的能力when.这使它更像是if和unless.
given( $element ){
... when @list;
}
Run Code Online (Sandbox Code Playgroud)
你可能认为你可以使用List :: Util :: first,但是有一些边缘条件使它成为问题.
在这个例子中,很明显我们想成功匹配0.不幸的是,这段代码failure每次都会打印.
use List::Util qw'first';
my $element = 0;
if( first { $element eq $_ } 0..9 ){
print "success\n";
} else {
print "failure\n";
}
Run Code Online (Sandbox Code Playgroud)
您可以检查已first定义的返回值,但如果我们确实希望匹配undef成功,则会失败.
grep但是你可以放心使用.
if( grep { $element eq $_ } 0..9 ){ ... }
Run Code Online (Sandbox Code Playgroud)
这是安全的,因为grep在标量上下文中调用.在标量上下文中调用时,数组返回元素数.所以即使我们试图匹配,这将继续有效undef.
你可以使用一个封闭的for循环.只要确保你打电话last,在成功的比赛中退出循环.否则,您可能会多次运行代码.
for( @array ){
if( $element eq $_ ){
...
last;
}
}
Run Code Online (Sandbox Code Playgroud)你可以将for循环放在if语句的条件中......
if(
do{
my $match = 0;
for( @list ){
if( $element eq $_ ){
$match = 1;
last;
}
}
$match; # the return value of the do block
}
){
...
}
Run Code Online (Sandbox Code Playgroud)...但是for在if声明之前放置循环可能更清楚.
my $match = 0;
for( @list ){
if( $_ eq $element ){
$match = 1;
last;
}
}
if( $match ){ ... }
Run Code Online (Sandbox Code Playgroud)如果您只是匹配字符串,您也可以使用哈希.如果你的程序@list很大,这可以加速你的程序,并且你将要%hash多次匹配.特别是如果@array不改变,因为那时你只需要加载%hash一次.
my %hash = map { $_, 1 } @array;
if( $hash{ $element } ){ ... }
Run Code Online (Sandbox Code Playgroud)您也可以制作自己的子程序.这是使用原型有用的情况之一.
sub in(&@){
local $_;
my $code = shift;
for( @_ ){ # sets $_
if( $code->() ){
return 1;
}
}
return 0;
}
if( in { $element eq $_ } @list ){ ... }
Run Code Online (Sandbox Code Playgroud)jro*_*way 15
if( $element ~~ @list ){
do_task
}
Run Code Online (Sandbox Code Playgroud)
~~ 是"智能匹配运算符",并且不仅仅列出成员资格检测.
$foo = first { ($_ && $_ eq "value" } @list; # first defined value in @list
Run Code Online (Sandbox Code Playgroud)
或者用于手动滚动类型:
my $is_in_list = 0;
foreach my $elem (@list) {
if ($elem && $elem eq $value_to_find) {
$is_in_list = 1;
last;
}
}
if ($is_in_list) {
...
Run Code Online (Sandbox Code Playgroud)
一个略有不同的版本可能会在很长的列表上更快一些:
my $is_in_list = 0;
for (my $i = 0; i < scalar(@list); ++$i) {
if ($list[i] && $list[i] eq $value_to_find) {
$is_in_list = 1;
last;
}
}
if ($is_in_list) {
...
Run Code Online (Sandbox Code Playgroud)
如果您计划多次执行此操作,则可以在空间中进行权衡以查找查找时间:
#!/usr/bin/perl
use strict; use warnings;
my @array = qw( one ten twenty one );
my %lookup = map { $_ => undef } @array;
for my $element ( qw( one two three ) ) {
if ( exists $lookup{ $element }) {
print "$element\n";
}
}
Run Code Online (Sandbox Code Playgroud)
假设元素出现的次数@array不重要且内容@array是简单的标量.
在perl> = 5.10时,智能匹配运算符肯定是最简单的方法,正如许多其他人已经说过的那样.
在旧版本的perl上,我建议使用List :: MoreUtils :: any.
List::MoreUtils 不是一个核心模块(有人说它应该是),但它非常受欢迎,它包含在主要的perl发行版中.
它具有以下优点:
in那样)而不是元素的值,List::Util::first如上所述(这使得很难测试);grep,它停在第一个通过测试的元素上(perl的智能匹配操作符也是短路的);以下示例适用于任何搜索(标量)值,包括undef:
use List::MoreUtils qw(any);
my $value = 'test'; # or any other scalar
my @array = (1, 2, undef, 'test', 5, 6);
no warnings 'uninitialized';
if ( any { $_ eq $value } @array ) {
print "$value present\n"
}
Run Code Online (Sandbox Code Playgroud)
(在生产代码中,最好缩小范围no warnings 'uninitialized').
TIMTOWTDI
sub is (&@) {
my $test = shift;
$test->() and return 1 for @_;
0
}
sub in (@) {@_}
if( is {$_ eq "a"} in qw(d c b a) ) {
print "Welcome in perl!\n";
}
Run Code Online (Sandbox Code Playgroud)
grep 在这里很有帮助
if (grep { $_ eq $element } @list) {
....
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
88088 次 |
| 最近记录: |