使用哈希引用时出现严格引用错误
Strict refs error when working with hash reference
我加入了我已经验证的代码来说明我的问题。我的 objective 是从此处模拟的数据库查询返回的哈希作为 %r(其中包含数字索引),并使用 "name" 字段的值作为接收哈希中的键。 (此哈希将包含多个查询的结果。)
我觉得我可能在引用和取消引用方面做了一些愚蠢的事情。我真的很想尝试掌握这里工作的概念。谢谢!
#!/usr/bin/perl -T
use strict;
use warnings;
my %hash;
my %r = (
'1' => {
name => 'Harry',
desc => 'Prince',
},
);
MergeHash(\%hash,\%r);
foreach my $name (keys %hash) {
print "name = $name, desc = $hash{$name}{desc}\n"; # EDIT: REVISED
}
exit;
sub MergeHash {
my $h = shift; # reference to receiving hash
my $r = shift; # reference to giving hash
foreach my $i (keys %{$r}) {
$$h{name} = $$r{$i}{name} || 'Unknown'; # okay
$$h{name}{desc} = $$r{$i}{desc} || 'Unknown'; # Can't use string ("Harry") as a HASH ref while "strict refs" in use at ./test.pl line 25.
}
}
编辑:根据要求,输出(也在上面的代码中作为注释指示):
Can't use string ("Harry") as a HASH ref while "strict refs" in use at ./test.pl line 25.
编辑 #2:修改打印行(在上面的代码中)以明确 %hash 中所需的结构。
$$h{name}{desc}
更清楚的写成
$h->{name}{desc}
的缩写
$h->{name}->{desc}
因为这更清楚,$h->{name}
的值被用作散列引用(就像 $h
的值刚才一样),但它包含一个字符串。
您只需将 name
替换为实际名称,因为这就是您想要的密钥。
for my $i (keys(%$r)) {
$h->{ $r->{$i}{name} }{desc} = $r->{$i}{desc};
}
我们实际上不需要$i
,所以我们简化一下。
for my $row (values(%$r)) {
$h->{ $row->{name} }{desc} = $row->{desc};
}
上面的问题是它不适合每行超过一个字段。以下内容处理得更好:
for my $row (values(%$r)) {
$h->{ $row->{name} } = {
desc => $row->{desc},
# ...
};
}
购买为什么要构建一个新的散列,而我们已经拥有的散列?
for my $row (values(%$r)) {
$h->{ $row->{name} } = $row;
}
如果您想用来自给定哈希的所有数据覆盖接收哈希的成员,那么下面的代码将起作用。
sub MergeHash {
my $h = shift; # reference to receiving hash
my $r = shift; # reference to giving hash
while (my ($k, $v) = each %$r) {
$h->{$k} = $v;
}
}
问题是 $$h 假定 $h 是对 SCALAR 的引用,但事实并非如此,它是对 HASH 的引用,您通常会看到人们在引用其成员时取消引用散列,因为我已完成以上操作。另一种方法是像这样声明散列的副本,但这不适用于您的用例:
my %copyofh = %$h;
我加入了我已经验证的代码来说明我的问题。我的 objective 是从此处模拟的数据库查询返回的哈希作为 %r(其中包含数字索引),并使用 "name" 字段的值作为接收哈希中的键。 (此哈希将包含多个查询的结果。)
我觉得我可能在引用和取消引用方面做了一些愚蠢的事情。我真的很想尝试掌握这里工作的概念。谢谢!
#!/usr/bin/perl -T
use strict;
use warnings;
my %hash;
my %r = (
'1' => {
name => 'Harry',
desc => 'Prince',
},
);
MergeHash(\%hash,\%r);
foreach my $name (keys %hash) {
print "name = $name, desc = $hash{$name}{desc}\n"; # EDIT: REVISED
}
exit;
sub MergeHash {
my $h = shift; # reference to receiving hash
my $r = shift; # reference to giving hash
foreach my $i (keys %{$r}) {
$$h{name} = $$r{$i}{name} || 'Unknown'; # okay
$$h{name}{desc} = $$r{$i}{desc} || 'Unknown'; # Can't use string ("Harry") as a HASH ref while "strict refs" in use at ./test.pl line 25.
}
}
编辑:根据要求,输出(也在上面的代码中作为注释指示):
Can't use string ("Harry") as a HASH ref while "strict refs" in use at ./test.pl line 25.
编辑 #2:修改打印行(在上面的代码中)以明确 %hash 中所需的结构。
$$h{name}{desc}
更清楚的写成
$h->{name}{desc}
的缩写
$h->{name}->{desc}
因为这更清楚,$h->{name}
的值被用作散列引用(就像 $h
的值刚才一样),但它包含一个字符串。
您只需将 name
替换为实际名称,因为这就是您想要的密钥。
for my $i (keys(%$r)) {
$h->{ $r->{$i}{name} }{desc} = $r->{$i}{desc};
}
我们实际上不需要$i
,所以我们简化一下。
for my $row (values(%$r)) {
$h->{ $row->{name} }{desc} = $row->{desc};
}
上面的问题是它不适合每行超过一个字段。以下内容处理得更好:
for my $row (values(%$r)) {
$h->{ $row->{name} } = {
desc => $row->{desc},
# ...
};
}
购买为什么要构建一个新的散列,而我们已经拥有的散列?
for my $row (values(%$r)) {
$h->{ $row->{name} } = $row;
}
如果您想用来自给定哈希的所有数据覆盖接收哈希的成员,那么下面的代码将起作用。
sub MergeHash {
my $h = shift; # reference to receiving hash
my $r = shift; # reference to giving hash
while (my ($k, $v) = each %$r) {
$h->{$k} = $v;
}
}
问题是 $$h 假定 $h 是对 SCALAR 的引用,但事实并非如此,它是对 HASH 的引用,您通常会看到人们在引用其成员时取消引用散列,因为我已完成以上操作。另一种方法是像这样声明散列的副本,但这不适用于您的用例:
my %copyofh = %$h;