是否有perl"not in"运算符?

tri*_*ity 15 perl

假设我有一个数组,我想确保所有这些都在一个集合(x,y,z)中,我正在检查以下计算结果为0:

scalar ( grep { $_ ne x && $_ ne y && $_ ne z } @arr )
Run Code Online (Sandbox Code Playgroud)

只是想知道如果我们在Perl中有"IN"和"NOT IN"类似sql的运算符也不会更容易..

scalar ( grep { $_ NOT IN (x,y,z) } @arr )
Run Code Online (Sandbox Code Playgroud)

还是已经有一个??

谢谢,三位一体

Eth*_*her 16

这里的库List :: UtilList :: MoreUtils在测试列表成员资格时非常有用,你不关心值本身,而只是存在.这些更有效grep,因为一旦找到匹配,它们就会停止循环遍历列表,这可以通过长列表加快速度.此外,这些模块是用C/XS编写的,比任何纯perl实现都要快.

use List::MoreUtils 'any';

my @list = qw(foo bar baz);

my $exists = any { $_ eq 'foo' } @list;
print 'foo ', ($exists ? 'is' : 'is not'), " a member of the list\n";

$exists = any { $_ eq 'blah' } @list;
print 'blah ', ($exists ? 'is' : 'is not'), " a member of the list\n";
Run Code Online (Sandbox Code Playgroud)

(如果您仅限于使用带有核心Perl的模块,则可以first在List :: Util中使用 - 它首先在5.7.3中附带perl.)


Eri*_*rom 14

解决此问题的典型方法是使用哈希:

my %set = map {$_ => 1} qw( x y z ); # add x, y and z to the hash as keys
                                     # each with a value of 1

my @not_in_set = grep {not $set{$_}} @arr;
Run Code Online (Sandbox Code Playgroud)


Rob*_*t P 11

如果您使用的是Perl 5.10或更高版本(或者愿意在perl 5.18及更高版本中使用实验性功能),智能匹配运算符将完全满足您的需求.

# if Perl 5.18 or higher; otherwise not needed
no warnings 'experimental::smartmatch';

my @filter = qw(X Y Z);
my $not_in_filter = scalar grep { ! ($_ ~~ @filter) } @array;
Run Code Online (Sandbox Code Playgroud)

如果Filter和/或@array很大,那么它可能很慢,因为它是O(N ^ 2).在这种情况下,您仍然可以使用智能匹配,只需更改过滤器:

my %filter = map { $_ => 1 } qw(X Y Z);
my $not_in_filter = scalar grep { ! ($_ ~~ %filter) } @array;
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅详细信息中的智能匹配perldoc perlsyn.

此外,如果需要支持5.10和5.18之间的perl版本,请考虑使用cpan模块experimental.这会进行版本检查,如果找到需要它的Perl版本,则包含"无警告".

use experimental 'smartmatch';
Run Code Online (Sandbox Code Playgroud)

请参阅:https://search.cpan.org/~leont/experimental-0.016/lib/experimental.pm

  • @trinity不幸的是,smartmatch系列功能在perl 5.18.0中被标记为实验,所以你可能不应该开始使用它. (3认同)