代码之家  ›  专栏  ›  技术社区  ›  fflyer05

在perl中构建可变深度散列引用数据结构

  •  3
  • fflyer05  · 技术社区  · 15 年前

    我需要在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,\%hash是如何生成的?

    3 回复  |  直到 15 年前
        1
  •  5
  •   Ether    15 年前

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

    美元/便士 %hash

        2
  •  1
  •   Greg Bacon    15 年前

    将显式标记添加到 $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!'
            }
          }
        }
      }
    };

    美元/便士 %hash .

        3
  •  1
  •   Axeman maxelost    15 年前

    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。