在perl中构建可变深度哈希引用数据结构

时间:2010-07-21 17:50:23

标签: perl

我需要在perl中构建一个可变深度哈希数据结构。最终我找到了这段代码:


#!/usr/bin/perl -w
use strict;

my %hash;
my $value = "foo";
my @cats = qw(a b c d);

my $p = \%hash;
foreach my $item (@cats) {
 $p->{$item} = {} unless exists($p->{$item});
 $p = $p->{$item};
}

我的问题是它的工作原理和原因。我以为我知道perl是如何工作的。在这段代码中,我没有看到\%hash值被重置,并且看起来每个循环都会重置$ p(这是一个局部变量)。我甚至可以用数据转储器看到它: 运行:


#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;

my %hash;
my $value = "foo";
my @cats = qw(a b c d);

my $p = \%hash;
foreach my $item (@cats) {
 print "BEFORE:\n";
 print Dumper(\%hash);
 #print Dumper($p);
 $p->{$item} = {} unless exists($p->{$item});
 $p = $p->{$item};
 print "AFTER:\n";
 print Dumper(\%hash);
 #print Dumper($p);
}

然后用

#print Dumper($p)
取消注释该行清除显示$ p每次都是一个新变量。

如果每次重置$ p,如何构建\%hash?

3 个答案:

答案 0 :(得分:5)

$p每次都没有“重置”;它被设置为哈希中的下一个较低级别,刚刚添加。此时它只是一个空的hashref {},因为它将在下一个循环迭代中填充。

我不确定你是如何得出结论$p每次都是一个新变量,但这是不正确的......它只是指向%hash结构中的新位置。由于它是在循环之外声明的,因此循环迭代时它不会丢失它的值。

答案 1 :(得分:1)

$p引用的哈希添加显式标记:

 ...
 print "AFTER:\n";
 $p->{'$p'} = 'is here!';
 print Dumper(\%hash);
 delete $p->{'$p'};
}

然后最后几个AFTER转储看起来像

AFTER:
$VAR1 = {
  'a' => {
    'b' => {
      'c' => {
        '$p' => 'is here!'
      }
    }
  }
};

AFTER:
$VAR1 = {
  'a' => {
    'b' => {
      'c' => {
        'd' => {
          '$p' => 'is here!'
        }
      }
    }
  }
};

是的,在每个新深度,$p引用空哈希,但后退一步以查看%hash的整体结构。

答案 2 :(得分:1)

想看到一些很酷的东西吗?这也是一样的(只有你从未看到它分配 hashref !)

my $p = \\%hash; # $p is a reference to a hashref
foreach my $item (@cats) {
    # because $p references a reference, you have to dereference
    # it to point to the hash.
    $p = \$$p->{$item} unless exists $$p->{$item};
}

一旦引用它就会为autovivified,当它像hashref一样被解决时,它会创建hashref。