问题描述
我有这个来源 第一次启动.pl
use strict;
use warnings;
use hh;
print "Starting...\n";
my $abc={
VAL=>['alfa','beta'],STUDENTS=>{
stud1=>{VAL=>['delta','gama']},stud2=>{VAL=>['omega','upsilon']},}
};
my $object=hh->new(catalog=>$abc);
和包裹
package hh;
use strict;
use warnings;
sub new {
my $class=shift;
my $self={@_};
bless ($self,$class) ;
$self->_initialize("",['BEGIN']);
return $self ;
}
sub _initialize {
my $self=shift;
my $tab=shift;
my $carry=shift;
$tab=$tab."\t|";
if (defined $self->{VAL}){print "$tab Have val=",join(" ",@{$self->{VAL}}),"\n";push(@{$carry},@{$self->{VAL}})}
foreach my $k (sort {lc $a cmp lc $b} keys %{$self}){
print $tab,"carry=",$#{$carry}+1," ",$k,"\n";
if (ref($self->{$k}) eq 'HASH'){print "$tab Running initialize pentru $k\n";_initialize($self->{$k},$tab,$carry)}
}
return $self;
}
1;
输出是这样的
Starting...
|carry=1 catalog
| Running initialize pentru catalog
| | Have val=alfa beta
| |carry=3 STUDENTS
| | Running initialize pentru STUDENTS
| | |carry=3 stud1
| | | Running initialize pentru stud1
| | | | Have val=delta gama
| | | |carry=5 VAL
| | |carry=5 stud2
| | | Running initialize pentru stud2
| | | | Have val=omega upsilon
| | | |carry=7 VAL
| |carry=7 VAL
不知何故,我想将树顶和遍历元素之间的 VAL 数组收集到一个数组中。方式是在第二级的最后一个 VAL 有 7 个元素。我只想拥有 2 个元素(alfa 和 beta)
这是预期的输出
Starting...
|carry=1 catalog
| Running initialize pentru catalog
| | Have val=alfa beta
| |carry=3 STUDENTS
| | Running initialize pentru STUDENTS
| | |carry=3 stud1
| | | Running initialize pentru stud1
| | | | Have val=delta gama
| | | |carry=5 VAL carry=5 (OK)
| | |carry=5 stud2
| | | Running initialize pentru stud2
| | | | Have val=omega upsilon
| | | |carry=7 VAL carry=5 (not ok this need only his values catalog alfa beta omega epsilon)
| |carry=7 VAL not ok (carry 3 only catalog alfa beta)
...
解决方法
如果只想累加当前分支中的值,则必须传递进位数组的副本。 [@$carry]
取消引用 arrayref $carry
并从元素创建一个新的 arrayref。我在函数的末尾保留了调试打印的原始参考。更自然的方式是写 $carry = [@$carry]
。
use strict;
use warnings;
package hh;
use Data::Dumper;
sub new {
my $class=shift;
my $self={@_};
bless ($self,$class) ;
$self->_initialize("",['BEGIN']);
return $self ;
}
sub _initialize {
my $self=shift;
my $tab=shift;
my $carry=shift;
$tab=$tab."\t|";
print "$tab _initialize() called with carry "," [",join(',',@$carry),"]\n";
my $new_carry = [@$carry];
if (defined $self->{VAL}){
print "$tab Have found val=",join(" ",@{$self->{VAL}}),"\n";
print "$tab pushing ","\n";
push(@{$new_carry},@{$self->{VAL}})
}
print $tab," carry=",$#{$new_carry}+1,@$new_carry),"]\n";
foreach my $k (sort {lc $a cmp lc $b} keys %{$self}){
if (ref($self->{$k}) eq 'HASH'){print "$tab Running initialize pentru $k\n";_initialize($self->{$k},$tab,$new_carry)}
}
print "$tab returning to previous level. carry was ","]\n";
return $self;
}
package main;
print "Starting...\n";
my $abc={
VAL=>['alfa','beta'],STUDENTS=>{
stud1=>{VAL=>['delta','gama']},stud2=>{VAL=>['omega','upsilon']},}
};
my $object=hh->new(catalog=>$abc);
打印:
Starting...
| _initialized called with carry [BEGIN]
| carry=1 [BEGIN]
| Running initialize pentru catalog
| | _initialized called with carry [BEGIN]
| | Have found val=alfa beta
| | pushing alfa beta
| | carry=3 [BEGIN,alfa,beta]
| | Running initialize pentru STUDENTS
| | | _initialized called with carry [BEGIN,beta]
| | | carry=3 [BEGIN,beta]
| | | Running initialize pentru stud1
| | | | _initialized called with carry [BEGIN,beta]
| | | | Have found val=delta gama
| | | | pushing delta gama
| | | | carry=5 [BEGIN,beta,delta,gama]
| | | | returning to previous level. carry was [BEGIN,beta]
| | | Running initialize pentru stud2
| | | | _initialized called with carry [BEGIN,beta]
| | | | Have found val=omega upsilon
| | | | pushing omega upsilon
| | | | carry=5 [BEGIN,omega,upsilon]
| | | | returning to previous level. carry was [BEGIN,beta]
| | | returning to previous level. carry was [BEGIN,beta]
| | returning to previous level. carry was [BEGIN]
| returning to previous level. carry was [BEGIN]