循环包含在散列中的数组

时间:2015-07-10 20:13:34

标签: arrays perl

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

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循环来浏览我的数组?

3 个答案:

答案 0 :(得分:4)

在Perl术语中,

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

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

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

答案 1 :(得分:3)

在这种情况下,您需要将它全部包装在数组解除引用块@{}中,以便perl知道您尝试取消引用哪个部分...

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

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

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

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

答案 2 :(得分:1)

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

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;
}