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

Posted

技术标签:

【中文标题】在 perl 中构建可变深度哈希引用数据结构【英文标题】:Building a variable depth hash reference data structure in perl 【发布时间】:2010-07-21 17:50:22 【问题描述】:

我需要在 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 是如何构建的?

【问题讨论】:

【参考方案1】:

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

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

【讨论】:

【参考方案2】:

$p 所指的哈希添加一个显式标记:

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

那么最后几个 AFTER 转储看起来像

之后:
$VAR1 = 
  '一个' => 
    'b' => 
      'c' => 
        '$p' => '来了!'
      
    
  
;

后:
$VAR1 = 
  '一个' => 
    'b' => 
      'c' => 
        'd' => 
          '$p' => '来了!'
        
      
    
  
;

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

【讨论】:

【参考方案3】:

想看一些很酷的东西吗?这做同样的事情(只是你永远不会看到它分配了 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,当它像哈希引用一样被寻址时,它会创建那个哈希引用。

【讨论】:

以上是关于在 perl 中构建可变深度哈希引用数据结构的主要内容,如果未能解决你的问题,请参考以下文章

Perl引用介绍

通过引用和标量变量传递 Perl 哈希

在 Perl 中测试两个哈希键是不是具有相同的结构

“在将哈希分配给 perl 中的哈希时,“不能使用字符串 (””) 作为哈希引用,而“严格引用”在使用时出现错误

perl 引用

Perl的浅拷贝和深度拷贝