假设我有一个数组,我想确保所有这些都在一个集合(x,y,z)中,我正在检查以下评估为0:
scalar ( grep { $_ ne x && $_ ne y && $_ ne z } @arr )
只是想知道如果我们在Perl中使用“IN”和“NOT IN”类似sql的运算符会不会更容易..
scalar ( grep { $_ NOT IN (x,y,z) } @arr )
或者已经有一个??
谢谢, 三位一体
答案 0 :(得分:16)
库List::Util或List::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";
(如果您仅限于使用带有核心Perl的模块,您可以在List :: Util中使用first
- 它首先在5.7.3中附带perl。)
答案 1 :(得分: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;
答案 2 :(得分: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;
如果Filter和/或@array很大,那么它可能很慢,因为它是O(N ^ 2)。在这种情况下,您仍然可以使用智能匹配,只需更改过滤器:
my %filter = map { $_ => 1 } qw(X Y Z);
my $not_in_filter = scalar grep { ! ($_ ~~ %filter) } @array;
有关详细信息,请参阅perldoc perlsyn
中的Smart Matching in Detail。
另外,如果需要支持5.10和5.18之间的perl版本,请考虑使用cpan模块experimental
。这会进行版本检查,如果找到需要它的Perl版本,则包含“无警告”。
use experimental 'smartmatch';
请参阅:https://search.cpan.org/~leont/experimental-0.016/lib/experimental.pm
答案 3 :(得分:4)
如果阵列中有不到几百万个不同的东西,你也可以使用 使用散列设置差异的教科书方法:
my %seen;
@seen{ @arr } = (); # Create a key for every distinct value in @arr
delete @seen{ qw(x y z) }; # And remove the ones for x, y, and z
if (keys %seen) {
# There was something in @arr that's not x, y, or z
} else {
# There wasn't
}
答案 4 :(得分:4)
my $target = 'bar';
my @look_in = ('foo','baz','bar','etc');
if( $target ~~ @look_in) {
print "target is in array ";
}
~~在数组中
my $target = 'bar';
my @look_in = ('foo','baz','bar','etc');
if( not $target ~~ @look_in) {
print "target is not in array";
}
这叫做smartmatch,有些人建议不要使用它们,但它们对字符串列表的效果相当不错。
答案 5 :(得分:2)
use List::Member;
my $target = 'bar';
my @look_in = ('foo','baz','bar','etc');
if( member($target, @look_in) + 1) {
print "It's a member of the array\n";
}
这可以解决问题