【问题标题】:Looping through array contained in a hash遍历包含在哈希中的数组
【发布时间】:2015-07-12 22:33:34
【问题描述】:

所以我有一个包含数组的对象:

package MyObject;

sub new {
    my($type) = @_;
    my $self->{Params}{Status}{Packages} = [];
}

我有一个添加新的包子,它附加到这个“包”数组上,如:

sub add_package {
    my($self, $package_obj) = @_;

    push $self->{Params}{Status}{Packages}, $package;
}

现在,当我去查找阵列中的所有包时,我遇到了问题。每当我尝试像这样取出包裹时:

foreach my $package($self->{Params}{Status}{Packages}) {
    # do something with $package. 
}

这只会循环一次。现在据我了解,哈希实际上存储了一个指向数组的指针,所以我尝试这样做:

foreach my $package(@$self->{Params}{Status}{Packages}) {
    # do something with $package. 
}

然后有一个错误说 $self 不是一个数组。我确实注意到了:

scalar $self->{Params}{Status}{Packages};

返回:

@ARRAY(0xSome Address);

我错过了什么?以及如何使用foreach 循环来遍历我的数组?

【问题讨论】:

    标签: arrays perl


    【解决方案1】:

    $self->{Params}{Status}{Packages} 是一个数组的reference,在 Perl 术语中。当你有对某事的引用时,把它前面的正确字符放在dereference it。如果引用不仅仅是前面可能带有一些符号的名称,则需要用大括号将其括起来。这是一个优先级问题:@$self->{Params}{Status}{Packages} 被解析为(@$self)->{Params}{Status}{Packages},但你需要

    @{$self->{Params}{Status}{Packages}}
    

    即由表达式 $self->{Params}{Status}{Packages} 引用的数组。

    【讨论】:

      【解决方案2】:

      在这种情况下,您需要将其全部包装在数组解引用块 @{} 中,以便 perl 知道您要解引用的部分...

      for my $package (@{ $self->{Params}{Status}{Packages} }){
          print "$package\n";
      }
      

      另外,为了保持一致,我更喜欢在提取或插入时始终使用块取消引用数组:

      push @{ $self->{Params}{Status}{Packages} }, $package;
      

      更新:从 5.24.0+ 开始,autoderef(使用 keys()values()each() 和引用)几乎肯定会被删除,并替换为后缀引用。但是,使用 @{}%{} 将继续受到支持,并且向后兼容,因此我建议始终使用它们。

      【讨论】:

        【解决方案3】:

        在我看来,最清晰的方法是将数组引用提取到一个临时标量变量,这使得访问数组非常简单

        my $packages = $self->{Params}{Status}{Packages};
        for my $package ( @$packages ) {
            # do something with $package. 
        }
        

        此外,如果您按照应有的方式启用了 use strictuse warnings,您的 add_package 子例程将生成消息

        push on reference is experimental
        

        这不是您可以放心忽略的事情。实验特性可能会改变它们的行为或在 Perl 的更高版本中完全消失,在生产代码中使用它们是不明智的。你可以用类似的方式修复你的子程序,像这样

        sub add_package {
            my ($self, $package_obj) = @_;
        
            my $packages = $self->{Params}{Status}{Packages};
            push @$packages, $package;
        }
        

        【讨论】:

          猜你喜欢
          • 2012-08-22
          • 1970-01-01
          • 2016-08-19
          • 2016-09-03
          • 1970-01-01
          • 1970-01-01
          • 2014-12-30
          • 1970-01-01
          相关资源
          最近更新 更多