使用哈希引用时出现严格引用错误

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;