Pau RS Pau RS - 12 days ago 8
Perl Question

Why does the second array gets modified?

I just want to assign the value of the AB array to the last position of the ABU array.

$ABU->[1][-1][1] = $AB->[1][$i][1];


And every time this assignation occurs, the AB array gets modified.

for ($i = 1; $i < $lenghtf; $i++) {
if ($ABU->[1][-1][1] < $AB->[1][$i][0]) {
push (@{$ABU->[1]}, $AB->[1][$i]);
} elsif ($ABU->[1][-1][1] < $AB->[1][$i][1]){
$ABU->[1][-1][1] = $AB->[1][$i][1];
}
}


If I do

print Dumper ($AB[1]);


before the loop and

print Dumper {ABU => $ABU, AB => $AB};


after the loop, I get this output:

![enter image description here][1]

After people's answers, I have realised that the problem may be when I assign the first value to ABU[1] before the loop:

push (@{$ABU->[1]}, $AB->[1][0]);


If I do print with dumper before the loop:

enter image description here

I've tried to change that firs asignation syntax:

push (@{$ABU->[1]}, @{$AB->[1][0]});


And then the Dumper looks better:

enter image description here

The problem now is that I don't know why when I run the for loop it complains in the first if line:

if ($ABU->[1][-1][1] < $AB->[1][$i][0]) {


with this STDERR:

Can't use string ("15") as an ARRAY ref while "strict refs"

Answer

The problem is this line

push (@{$ABU->[1]}, $AB->[1][$i]);

Here you clearly insert a reference to the array. It will be seen at result of print Dumper {ABU => $ABU, AB => $AB}; which is missing in your question. But it can be seen in the next image.

image

See this $VAR->{ABU}[1][0]. After few cycles, you will end up with multiple references to the same array.

For your data format, you can do

push @{$ABU->[1]}, [@{$AB->[1][$i]}];

But using some cloning routine would be more robust (immune to the feature code changes which inevitably come with time).

use Storable qw(dclone);
push @{$ABU->[1]}, dclone($AB->[1][$i]);

BTW your code could be written

use Storable qw(dclone);
for my $ab_row (@{$AB->[1]}) {
    my $last_abu_row = $ABU->[1][-1];
    if ($last_abu_row->[1] < $ab_row->[0]) {
        push @{$ABU->[1]}, dclone($ab_row);
    } elsif ($last_abu_row->[1] < $ab_row->[1]) {
        $last_abu_row->[1] = $ab_row->[1];
    }
}