2010-07-21 64 views
3

我需要在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是如何工作的。在这段代码中,我没有看到\%哈希值被重置,并且$ 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,\%哈希将如何生成?

回答

5

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

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

1

添加一个明确的标记,其$p指散:

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

然后近一后堆放样子

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

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

是,在每一个新的深度,$p指空的散列,但退一步看看%hash的整体结构。

+0

非常感谢。这也有助于清理事情 – fflyer05 2010-07-21 19:02:40

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。