2010-07-21 40 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。