【问题标题】:Accessing hash reference in perl在 perl 中访问哈希引用
【发布时间】:2011-05-31 21:38:27
【问题描述】:

我想知道是否可以在 perl 中执行以下操作。它将节省 40-50 行代码。

我有一个如下的哈希数据结构:

hash_Ref->{a}->{b}->{c}->{d}->{e}->{'count'}=30

我想知道有没有办法可以做到以下几点:

my $hash_ref_1 = ash_Ref->{a}->{b}->{c}->{d};

然后使用:

$hash_ref_2->{e}. 

总而言之,我想将哈希引用存储到变量中层次结构中的点“x”,然后访问点“x”指向的引用。我认为这在上面的示例中更加清楚。

更多细节

我尝试了几件事,但似乎对我不起作用。我正在复制代码,但不是我试图复制哈希的所有内容。我得到的输出也是这样的

 $VAR1 = {
          'e' => {
                   'count' => 2
                 },
          'c' => {
                   'count' => 2
                 },
          'a' => {
                   'count' => 2
                 },
          'b' => {
                   'count' => 2
                 },
          'd' => {
                   'count' => 2
                 }
        };

我期望这样的地方:

'a' => { 'count' => 2, 'b' => { 'count' => 2, 'c' => ......} }  

这是我使用的一些代码:

use strict;
use Data::Dumper;

my @array1 = ('a','b','c','d','e');
my @array2 = ('a','b','c','d','e');
my $hash;

 build_hash(\@array1);
 build_hash(\@array2);


sub build_hash {

    my @array = @{shift @_};

    my $hash_ref;

    for ( my $i =0 ;  $i < scalar @array ; $i++ ){

        print "$i \t $array[$i] \n";
         if ( exists $hash->{$array[$i]} ){

            $hash->{$array[$i]}->{'count'}++;
        }

        else{

            $hash->{$array[$i]}->{'count'}=1;
        }
    }
    print Dumper($hash);

}

我想根据 perl 中的元素按顺序构建哈希引用的层次结构,并可能使用一个循环,就像我在示例代码中尝试做的那样。

谢谢! -阿比

【问题讨论】:

  • 你试过什么?它有效吗?如果不是,为什么不呢? perllol and perldsc are must-reads
  • 只是对风格的评论:来自perldoc perlreftut(p3rl.org/reftut)的“箭头规则”hash_Ref-&gt;{a}-&gt;{b}-&gt;{c}-&gt;{d}-&gt;{e}-&gt;{'count'}可以写成hash_Ref-&gt;{a}{b}{c}{d}{e}{'count'}
  • 为什么$hash_ref_2 应该包含任何内容?

标签: perl perl-data-structures


【解决方案1】:
# 'a' => { 'count' => 2, 'b' => { 'count' => 2, 'c' => ......} }

sub build_hash {
    $_[0] ||= {};
    my $hash = shift;
    for (@_) {
        $hash = $hash->{$_} ||= {};
        ++$hash->{count};
    }
}

build_hash($hash, @array1);
build_hash($hash, @array2);

如果你想使用自动生存,你可以这样写:

sub build_hash {
    my $p = \shift;
    for (@_) {
        $p = \( $$p->{$_} );
        ++$$p->{count};
    }
}

build_hash($hash, @array1);
build_hash($hash, @array2);

另请参阅:Data::Diver

【讨论】:

  • @ikegami:非常感谢。只是想知道您是否会推荐任何好的资源来很好地掌握 perl 中的这些技术。
  • @Ahbi,你总是在修改同一个哈希值。您想修改其他哈希。那些哈希不存在。因此,您需要创建它们。你的问题与 Perl 无关,所以没有 Perl 技术的书会有所帮助。
  • @ikegami :我应该更明确一点。我想问一个关于 perl 中复杂数据结构的好资源。你能告诉我 $_[0] ||= {}; 背后的理由吗?在第一个程序中。我肯定错过了什么。
  • @Abhi,在我的版本中,$hash 不是全局变量。如果您在本地 var $hash 中创建哈希引用(例如通过自动激活),它不会影响调用者中的变量。另一方面,修改$_[0]会改变调用者中的变量。
  • @ikegami :非常感谢您迄今为止的帮助。你肯定在帮助我学习关于 perl 的新知识。我有另一个关于程序的后续问题。您能否解释一下 $hash = $hash->{$_} ||= {} 行将如何工作。因此,每次有一个新条目时,都会创建一个匿名散列,但它如何被合并到具有层次结构的主大散列中。我仍然对这部分感到困惑。
【解决方案2】:

这应该像您认为的那样工作。附带说明一下,有时当您拥有...的哈希值时,您真正想要的是一个带有复合键的哈希值,例如 $h{"$a,$b,$c"} $h{$a}{$b}{$c}。只是要记住的事情。不知道这里是否适用。

【讨论】:

  • @frankc :我在原始问题中添加了更多详细信息 + 完整代码。
  • @frankc:我没有细节可以证明这一点,但这听起来像是一个可怕且不必要的扳手,尽管如此。没有downvote,但我不会使用它!
  • 您认为复合键比 6 层深度数据结构更难理解?我从未测量过它,但我敢打赌复合键也更有效。
  • 事实上,我个人认为复合比嵌套更难阅读,但让我们接受你的前提。你要向我保证你永远不会在你的哈希键中使用“,”吗?我知道这并不常见,但是如果您基于它构建一个大型系统并且有人违反了该承诺,那么您的整个数据结构就会崩溃。进一步使用它,你需要用逗号分割键:额外的不必要的工作。如果您想向其中一个键添加一些数据怎么办?以前是一个哈希,很容易将更多信息塞进去,现在它是逗号分隔列表的一部分,而不是一个单独的单元!
  • 最后,它没有必要,也无济于事。由于他是新手,所以不要将他与不明智的技巧混淆,并教他使用正确的 Perl。如果他愿意,他可以在以后搞砸,当他知道自己在做什么时。
猜你喜欢
  • 2011-12-29
  • 1970-01-01
  • 1970-01-01
  • 2013-06-06
  • 2017-07-05
  • 2012-03-10
  • 2016-12-12
  • 1970-01-01
  • 2015-06-26
相关资源
最近更新 更多