我有一个包含2个散列的脚本,在打印出内容时,我发现该脚本正在为第二个散列分配一个值,而我没有这样做。我先读取第一个哈希,然后读取第二个,然后再读取整个第二个哈希。它在hash2中只应包含1个条目,但现在包含2个条目。如何在这里分配hash2中的James值?
my %hash1 = ();
my %hash2 = ();
$hash1{"James"}{"1 Main Street"}++;
$hash1{"John"}{"2 Elm Street"}++;
$hash2{"John"}{"3 Oak Street"}++;
foreach my $name (keys %hash1) {
print "Hash1 Name $name\n";
foreach my $address (keys %{$hash1{$name}}) {
print "Hash1 Address $address\n";
foreach my $address (keys %{$hash2{$name}}) {
print "Hash2 Address $address\n";
}
}
}
print "\n";
foreach my $name (keys %hash2) {
print "Hash2 Name $name\n";
foreach my $address (keys %{$hash2{$name}}) {
print "Hash2 Address $address\n";
}
}
输出看起来像这样:
Hash1 Name James
Hash1 Address 1 Main Street
Hash1 Name John
Hash1 Address 2 Elm Street
Hash2 Address 3 Oak Street
Hash2 Name James
Hash2 Name John
Hash2 Address 3 Oak Street
答案 0 :(得分:1)
当您尝试从哈希2读取不存在的密钥时,正在创建第二个值。
my %hash1 = ();
my %hash2 = ();
$hash1{"James"}{"1 Main Street"}++;
$hash1{"John"}{"2 Elm Street"}++;
$hash2{"John"}{"3 Oak Street"}++;
foreach my $name (keys %hash1) {
print "Hash1 Name $name\n";
foreach my $address (keys %{$hash1{$name}}) {
print "Hash1 Address $address\n";
next unless exists $hash2{$name}; # check if the key exists in second hash before trying to use the key in $hash2
foreach my $address (keys %{$hash2{$name}}) { #second value gets created here
print "Hash2 Address $address\n";
}
}
}
print "\n";
foreach my $name (keys %hash2) {
print "Hash2 Name $name\n";
foreach my $address (keys %{$hash2{$name}}) {
print "Hash2 Address $address\n";
}
}
答案 1 :(得分:1)
当您使用未定义的值作为参考时,Perl进行所需的参考排序,然后尝试执行该操作。这称为“自动生存”。
这是一个小示范。变量以未定义开始。然后,将其视为数组引用(取消获取第0个元素的引用):
use Data::Dumper;
my $empty;
print Dumper( $empty );
my $value = $empty->[0];
print Dumper( $empty );
Perl将$empty
转换为数组引用,然后尝试从中获取第0个元素。剩下的是以前曾经有undef
的数组引用:
$VAR1 = undef;
$VAR1 = [];
这是预期的行为。
再走一步。将undef
放入数组中,然后将该元素视为数组引用:
use Data::Dumper;
my @array = ( 1, undef, 'red' );
print Dumper( \@array );
my $value = $array[1]->[0];
print Dumper( \@array );
现在第二个元素是一个空数组引用:
$VAR1 = [
1,
undef,
'red'
];
$VAR1 = [
1,
[],
'red'
];
再走一步。不要存储undef
值。而是访问数组中最后一项之后的数组位置:
use Data::Dumper;
my @array = ( 1, 'red' );
print Dumper( \@array );
my $value = $array[2]->[0];
print Dumper( \@array );
现在,您在数组中获得一个数组引用元素。现在再增加一个元素:
$VAR1 = [
1,
'red'
];
$VAR1 = [
1,
'red',
[]
];
如果您走得更远(例如,元素5),则用undef
将填满元素直到所需的元素:
use Data::Dumper;
my @array = ( 1, 'red' );
print Dumper( \@array );
my $value = $array[5]->[0];
print Dumper( \@array );
$VAR1 = [
1,
'red'
];
$VAR1 = [
1,
'red',
undef,
undef,
undef,
[]
];
散列的工作方式相同,这就是您所看到的。当您要检查James
下是否有第二级密钥时,Perl需要创建James
密钥,并为其提供一个空的哈希引用值以进行检查。该二级密钥不存在,但是“ James”的一级密钥仍然存在:
use Data::Dumper;
my %hash = (
John => { Jay => '137' },
);
print Dumper( \%hash );
if( exists $hash{James}{Jay} ) {
print $hash{James}{Jay};
}
print Dumper( \%hash );
现在您会看到一个额外的键:
$VAR1 = {
'John' => {
'Jay' => '137'
}
};
$VAR1 = {
'James' => {},
'John' => {
'Jay' => '137'
}
};
在这种情况下,您不喜欢此功能,但是可以使用no autovivification
编译指示将其关闭。这是您需要首先安装的CPAN模块:
no autovivification;
use Data::Dumper;
my %hash = (
John => { Jay => '137' },
);
print Dumper( \%hash );
if( exists $hash{James}{Jay} ) {
print $hash{James}{Jay};
}
print Dumper( \%hash );
您没有得到额外的钥匙:
$VAR1 = {
'John' => {
'Jay' => '137'
}
};
$VAR1 = {
'John' => {
'Jay' => '137'
}
};
您可能还想阅读How can I check if a key exists in a deep Perl hash?。我展示了一种方法,可让您检查嵌套的哈希而不创建中间级别。