在Perl中,我有一个使用类似于以下
的循环创建的哈希哈希 my %HoH
for my $i (1..10) {
$HoH{$a}{$b} = $i;
}
$ a和$ b是在HoH填写时确实具有某些值的变量。在创建HoH之后,如何检查HoH中是否存在特定的对($ c,$ d)?以下不起作用
if (defined $HoH{$c}{$d}) {...}
因为如果已经在HoH中不存在$ c,它将被创建为没有值的键。
答案 0 :(得分:4)
书写
if (defined $HoH{$c}{$d}) {...}
会“工作”,因为它会告诉你$HoH{$c}{$d}
是否有定义的值。问题是,如果$HoH{$c}
尚不存在,则会创建它(具有适当的值),以便可以测试$HoH{$c}{$d}
。这个过程称为“自动化”。设置值时很方便,例如
my %hoh;
$hoh{a}{b} = 1; # Don't need to set '$hoh{a} = {}' first
但在检索可能不存在的值时不方便。我希望Perl足够聪明,只能对用作左值和短路的表达式执行自动修复,以便为rvalues返回undef
,但是,唉,这不是那么神奇。 autovivification pragma(在CPAN上可用)添加了执行此操作的功能。
为避免自动更新,您需要先测试中间值:
if (exists $HoH{$c} && defined $HoH{$c}{$d}) {
...
}
答案 1 :(得分:3)
use Data::Dumper;
my %HoH;
$HoH{A}{B} = 1;
if(exists $HoH{C} && exists $HoH{C}{D}) {
print "exists\n";
}
print Dumper(\%HoH);
if(exists $HoH{C}{D}) {
print "exists\n";
}
print Dumper(\%HoH);
输出:
$VAR1 = {
'A' => {
'B' => 1
}
};
$VAR1 = {
'A' => {
'B' => 1
},
'C' => {}
};
自动生成导致创建密钥。我的第二个示例中的“exists”显示了这一点,因此第一个示例单独检查两个键。
答案 2 :(得分:2)
有几种方法:
if ( $HoH{$c} && defined $HoH{$c}{$d} ) {...}
或
if ( defined ${ $HoH{$c} || {} }{$d} ) {...}
或
no autovivification;
if (defined $HoH{$c}{$d}) {...}
或
use Data::Diver;
if ( defined Data::Diver::Dive( \%HoH, $c, $d ) ) {...}
答案 3 :(得分:0)
您必须使用exists功能
存在EXPR
给定一个指定一个表达式 哈希的元素,如果是,则返回true 哈希中的指定元素曾经存在过 已经初始化,即使是 相应的值未定义。
请注意,EXPR可以是任意的 只要决赛复杂 operation是哈希或数组键 查找或子程序名称:
- if(exists $ ref-> {A} - > {B} - > {$ key}){}
- if(exists $ hash {A} {B} {$ key}){}
醇>
答案 4 :(得分:0)
我的看法:
use List::Util qw<first>;
use Params::Util qw<_HASH>;
sub exists_deep (\[%$]@) {
my $ref = shift;
return unless my $h = _HASH( $ref ) // _HASH( $$ref )
and defined( my $last_key = pop )
;
# Note that this *must* be a hash ref, for anything else to make sense.
return if first { !( $h = _HASH( $h->{ $_ } )) } @_;
return exists $h->{ $last_key };
}
您也可以递归地执行此操作。您还可以创建一个下降结构,允许中间甚至是终端arrayref,只需要一些额外的编码。