2015-07-10 107 views
2

所以,我有包含数组的对象:通过阵列循环

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

但后来有一个错误,指出$自我不是一个数组。我也注意到,当我做:

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

它返回:

@ARRAY(0xSome Address); 

我缺少什么?我怎样才能使用foreach循环来通过我的数组?

回答

3

在这种情况下,你需要用它所有的数组取消引用块@{}这样的perl知道你要提领这部分...

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

而且,只是为了保持一致,我喜欢解压时,或插入到总是DEREF与块阵列:

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

UPDATE:作为5.24.0+,autoderef(使用keys()values()each()与参考)将几乎certa将被删除,并替换为后缀引用。但是,使用@{}%{}将继续得到支持,并向后兼容,因此我建议您始终使用它们。

4

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

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

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

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