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

时间:2017-07-14 22:46:44

标签: perl reference dereference

我包含的代码已经过验证,说明了我的问题。我的目标是从这里模拟的数据库查询返回的哈希值为%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中所需的结构。

2 个答案:

答案 0 :(得分:3)

$$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;
}

答案 1 :(得分:-2)

如果要使用给定哈希中的所有数据覆盖接收哈希的成员,则以下代码将起作用。

my %copyofh = %$h;

问题是$$ h假设$ h是对SCALAR的引用而它不是,它是对HASH的引用,你通常会看到人们在引用其成员时解除引用哈希,就像我所做的那样以上。另一种方法是声明这样的哈希副本,但这对你的用例不起作用:

class Order(models.Model):
    # The relavant order fields which you require, i.e. order number etc.
    customer = models.ForeignKey(Customer, on_delete=models.CASCADE)