Perl 无赋值的哈希加法
我有一个包含2个散列的脚本,当我打印出内容时,我发现脚本正在为第2个散列赋值,而我没有这样做。我先读第一个散列,然后读第二个,然后再读第二个散列。在hash2中它应该只包含1个条目,但现在它包含2个条目。如何在这里分配hash2中的值JamesPerl 无赋值的哈希加法,perl,Perl,我有一个包含2个散列的脚本,当我打印出内容时,我发现脚本正在为第2个散列赋值,而我没有这样做。我先读第一个散列,然后读第二个,然后再读第二个散列。在hash2中它应该只包含1个条目,但现在它包含2个条目。如何在这里分配hash2中的值James my %hash1 = (); my %hash2 = (); $hash1{"James"}{"1 Main Street"}++; $hash1{"John"}{"2 Elm Street"}++; $hash2{"John"}{"3 Oak St
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
第二个值是在尝试从散列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";
}
}
第二个值是在尝试从散列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";
}
}
当您将未定义的值当作引用来使用时,Perl会对所需的引用进行排序,然后尝试执行该操作。这被称为“自动活体化” 这里有一个小演示。变量一开始是未定义的。然后将其视为数组引用(获取第0个元素的解引用): Perl将
$empty
转换为数组引用,然后尝试从中获取第0个元素。剩下的是一个数组引用,以前的unde
:
$VAR1 = undef;
$VAR1 = [];
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,
[]
];
这是故意的行为
更进一步。将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'
];
现在,第二个元素是空数组引用:
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),那么您想要的元素之前的间隙元素将被unde
“填充”:
$VAR1 = undef;
$VAR1 = [];
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
键,并给它一个空的hash ref值,它可以进行检查。第二级钥匙不在那里,但“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'
}
};
$VAR1 = {
'John' => {
'Jay' => '137'
}
};
$VAR1 = {
'John' => {
'Jay' => '137'
}
};
在这种情况下,您不喜欢此功能,但可以使用no autovification
pragma将其关闭。这是一个需要首先安装的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 = {
'James' => {},
'John' => {
'Jay' => '137'
}
};
$VAR1 = {
'John' => {
'Jay' => '137'
}
};
$VAR1 = {
'John' => {
'Jay' => '137'
}
};
你可能也喜欢阅读。我展示了一个方法,该方法允许您在不创建中间级别的情况下检查嵌套哈希。当您将未定义的值当作引用使用时,Perl会对所需的引用排序,然后尝试执行该操作。这被称为“自动活体化” 这里有一个小演示。变量一开始是未定义的。然后将其视为数组引用(获取第0个元素的解引用): Perl将
$empty
转换为数组引用,然后尝试从中获取第0个元素。剩下的是一个数组引用,以前的unde
:
$VAR1 = undef;
$VAR1 = [];
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,
[]
];
这是故意的行为
更进一步。将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'
];
现在,第二个元素是空数组引用:
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),那么您想要的元素之前的间隙元素将被unde
“填充”:
$VAR1 = undef;
$VAR1 = [];
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
键,并给它一个空的hash ref值,它可以进行检查。第二级钥匙不在那里,但“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'
}
};
$VAR1 = {
'John' => {
'Jay' => '137'
}
};
$VAR1 = {
'John' => {
'Jay' => '137'
}
};
在这种情况下,您不喜欢此功能,但可以使用no autovification
pragma将其关闭。这是一个需要首先安装的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 = {
'James' => {},
'John' => {
'Jay' => '137'
}
};
$VAR1 = {
'John' => {
'Jay' => '137'
}
};
$VAR1 = {
'John' => {
'Jay' => '137'
}
};
你可能也喜欢阅读。我展示了一种方法,允许您在不创建中间层的情况下检查嵌套哈希。对空哈希引用的不存在值
$hash2{'James'}
触发器应用hash de reference%{}
,并因此将键James
添加到%hash2
@StefanBecker,而不是所有的解引用,只是那些被认为是更新的。不幸的是,它可能总是包含键,实际上,您创建了4个哈希元素而没有分配给它们:$hash1{“James”}
,$hash1{“John”}
,$hash2{“James”}
和$hash2{“John”}
。这一切都是由于自生。就像左值上下文中的$$hash1{“James”}{“1 Main Street”}
是${$hash1{“James”}/={}{“1 Main Street”}
的缩写,左值上下文中的%{$hash2{$name}
是%{$hash2{$name}/=}
的缩写,在不存在的值$hash2}{James
触发空散列引用,因此也将键James
添加到%hash2
@StefanBecker,不是所有的解引用,只是那些被认为是更新的。不幸的是,它可能总是包含键,实际上,您创建了4个哈希元素而没有分配给它们:$hash1{“James”}
,$hash1{“John”}
,$hash2{“James”}
和$hash2{“John”}
。这一切都是由于自生。就像左值上下文中的$$hash1{“James”}{“1 Main Street”}
是${$hash1{“James”}/={}{“1 Main Street”}
的缩写,左值上下文中的%{$hash2{$name}
是%{$hash2{$name}/=}
的缩写,谢谢您的帮助