问题描述
我正在寻找列表中某个元素的存在.
I'm looking for presence of an element in a list.
在Python中,有一个in
关键字,我会做类似的事情:
In Python there is an in
keyword and I would do something like:
if element in list:
doTask
Perl中是否存在等效功能,而无需手动遍历整个列表?
Is there something equivalent in Perl without having to manually iterate through the entire list?
推荐答案
更新:
在v5.10.0中添加并在v5.10.1中进行了重大修改的智能匹配一直是人们经常抱怨的问题.尽管有很多方法可以使用它,但对于Perl的用户和实现者来说,它也被证明是有问题和令人困惑的.关于如何最好地解决该问题,已经有许多建议.显然,smartmatch几乎肯定会在未来发生变化或消失.不建议依靠其当前行为.
Smart match, added in v5.10.0 and significantly revised in v5.10.1, has been a regular point of complaint. Although there are a number of ways in which it is useful, it has also proven problematic and confusing for both users and implementors of Perl. There have been a number of proposals on how to best address the problem. It is clear that smartmatch is almost certainly either going to change or go away in the future. Relying on its current behavior is not recommended.
现在将在解析器看到~~,给定或何时发出警告.
Warnings will now be issued when the parser sees ~~, given, or when.
如果您可以不再需要Perl v5.10,则可以使用以下任何示例.
-
智能匹配
~~
运算符If you can get away with requiring Perl v5.10, then you can use any of the following examples.
The smart match
~~
operator.if( $element ~~ @list ){ ... } if( $element ~~ [ 1, 2, 3 ] ){ ... }
-
您还可以使用
given
/when
构造.在内部使用智能匹配功能. You could also use the
given
/when
construct. Which uses the smart match functionality internally.given( $element ){ when( @list ){ ... } }
-
您还可以将
for
循环用作"topicalizer"(这意味着它设置了$_
). You can also use a
for
loop as a "topicalizer" ( meaning it sets$_
).for( @elements ){ when( @list ){ ... } }
在Perl 5.12中将会出现的一件事是使用
when
的后缀版本的能力.这使得它甚至更像if
和unless
.One thing that will come out in Perl 5.12 is the ability to use the post-fix version of
when
. Which makes it even more likeif
andunless
.given( $element ){ ... when @list; }
如果您必须能够在旧版本的Perl上运行,那么仍然有几种选择.
-
您可能会认为您可以使用列表: :Util :: first ,但是有一些边缘条件使它有问题.
If you have to be able to run on older versions of Perl, there still are several options.
You might think you can get away with using List::Util::first, but there are some edge conditions that make it problematic.
在此示例中,很明显,我们希望成功匹配
0
.不幸的是,此代码每次都会打印failure
.In this example it is fairly obvious that we want to successfully match against
0
. Unfortunately this code will printfailure
every time.use List::Util qw'first'; my $element = 0; if( first { $element eq $_ } 0..9 ){ print "success\n"; } else { print "failure\n"; }
您可以检查
first
的返回值为了获得确定性,但是如果我们实际上希望与undef
的匹配成功,那将失败.You could check the return value of
first
for defined-ness, but that will fail if we actually want a match againstundef
to succeed.但是,您可以放心使用
grep
.You can safely use
grep
however.if( grep { $element eq $_ } 0..9 ){ ... }
这是安全的,因为
grep
在标量上下文中被调用.在标量上下文中调用时,数组返回元素的数量.因此,即使我们尝试与undef
匹配,这也将继续起作用.This is safe because
grep
gets called in a scalar context. Arrays return the number of elements when called in scalar context. So this will continue to work even if we try to match againstundef
.您可以使用封闭的
for
循环.只要确保调用last
,即可在成功匹配时退出循环.否则,您可能最终会多次运行代码.You could use an enclosing
for
loop. Just make sure you calllast
, to exit out of the loop on a successful match. Otherwise you might end up running your code more than once.for( @array ){ if( $element eq $_ ){ ... last; } }
-
您可以将
for
循环放入if
语句的条件内... You could put the
for
loop inside the condition of theif
statement ...if( do{ my $match = 0; for( @list ){ if( $element eq $_ ){ $match = 1; last; } } $match; # the return value of the do block } ){ ... }
-
...但是将
for
循环放在if
语句之前可能更清楚. ... but it might be more clear to put the
for
loop before theif
statement.my $match = 0; for( @list ){ if( $_ eq $element ){ $match = 1; last; } } if( $match ){ ... }
-
如果只匹配字符串,则还可以使用哈希.如果
@list
很大和,可以提高程序速度,您将与%hash
多次匹配.尤其是如果@array
不变,因为这样一来,您只需加载一次%hash
. If you're only matching against strings, you could also use a hash. This can speed up your program if
@list
is large and, you are going to match against%hash
several times. Especially if@array
doesn't change, because then you only have to load up%hash
once.my %hash = map { $_, 1 } @array; if( $hash{ $element } ){ ... }
-
您还可以创建自己的子例程.这是使用原型的有用情况之一.
You could also make your own subroutine. This is one of the cases where it is useful to use prototypes.
sub in(&@){ local $_; my $code = shift; for( @_ ){ # sets $_ if( $code->() ){ return 1; } } return 0; } if( in { $element eq $_ } @list ){ ... }
这篇关于Perl:if(list中的元素)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!