如果我有哈希
my %foo = ( foo => 1, bar => 1 );
我想检查%foo
中的任何键是否在比较数组中(显然键%foo只是一个数组)。我一直在想一些不存在的奇怪语法,如。
my @cmp0 = qw( foo baz );
my @cmp1 = qw( baz blargh );
if keys %foo in @cmp0 # returns true because key foo is in the array
if keys %foo in @cmp1 # returns false because no key in foo is an element of cmp1
最简单的方法是什么?
答案 0 :(得分:7)
List::MoreUtils有一个名为any
的函数,它使用类似于grep
的语法,但在第一次符合条件时停止其内部循环。这种行为的优点是需要的迭代次数要少得多(假设交叉点的随机分布)。
any
的另一个优点是代码清晰度:它以它的功能命名。 Perl最佳实践不鼓励在布尔上下文中使用grep
,因为grep
的假定用法是返回匹配的元素列表。它在布尔上下文中工作,但代码的意图对于读者来说不如any
那么明确,而any
是专为布尔使用而设计的。
use List::MoreUtils qw( any );
my %foo = ( foo => 1, bar => 1 );
my @cmp0 = qw( foo baz );
my @cmp1 = qw( baz blargh );
print "\@cmp0 and %foo have an intersection.\n"
if any { exists $foo{$_} } @cmp0;
print "\@cmp1 and %foo have an intersection.\n"
if any { exists $foo{$_} } @cmp1;
确实添加了对List :: MoreUtils的依赖。但是,List :: MoreUtils是无处不在的模块之一,很可能已经安装。
以下是一个例子:
~~
另一个选项是my %foo = ( foo => 1, bar => 1 );
my @cmp0 = qw( foo baz );
my @cmp1 = qw( baz blargh );
print "\@cmp0 and %foo have an intersection.\n" if @cmp0 ~~ %foo;
print "\@cmp1 and %foo have an intersection.\n" if @cmp1 ~~ %foo;
Smart Match Operator,它在Perl 5.10.0和更新版本中可用。它可以像这样使用:
any
使用smartmatch,您可以消除List :: MoreUtils依赖关系,转而支持最小的Perl版本依赖关系。您可以自行决定代码是否与{{1}}一样清晰。
答案 1 :(得分:5)
最简单的方法是将grep
与exists
运算符一起使用。
此代码
my %foo = ( foo => 1, bar => 1 );
my @cmp0 = qw( foo baz );
my @cmp1 = qw( baz blargh );
print "YES 0\n" if grep { exists $foo{$_} } @cmp0;
print "YES 1\n" if grep { exists $foo{$_} } @cmp1;
给出了这个输出
YES 0
答案 2 :(得分:5)
grep
是一个好主意,可能是最干净的。但是,您也可以使用logical OR assignment operator ||=
:
my $found;
$found ||= exists $foo{$_} for @cmp1;
答案 3 :(得分:1)
这些是简单的设置操作。
use strictures;
use Set::Scalar qw();
⋮
my $foo = Set::Scalar->new(keys %foo);
$foo->intersection(Set::Scalar->new(@cmp0))->size; # 1
$foo->intersection(Set::Scalar->new(@cmp1))->size; # 0
答案 4 :(得分:0)
有 - 像往常一样 - 有更多方法可以解决这个问题。你可以这样做:
#!/usr/bin/perl
use strict ;
use warnings ;
my %hash = ( foo => 1 , bar => 1 ) ;
my %cmp = ( cmp0 => [ qw(foo baz) ] ,
cmp1 => [ qw(baz blargh) ] ) ;
my @hash_keys = keys %hash ;
foreach my $compare ( keys %cmp ) {
my %tmp ;
# Generate a temporary hash from comparison keys via hash slice
@tmp{@{$cmp{$compare}}} = undef ;
INNER:
foreach my $hash_key ( @hash_keys ) {
if( exists $tmp{$hash_key} ) {
printf "Key '%s' is part of '%s'.\n" , $hash_key , $compare ;
last INNER ;
}
}
}
这给出了:
Key 'foo' is part of 'cmp0'.