为什么第二个数组会被修改?

时间:2016-11-26 23:00:19

标签: arrays perl

我只想将AB数组的值赋给ABU数组的最后位置。

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

每次进行此分配时,AB数组都会被修改。

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

如果我这样做

print Dumper ($AB[1]);
在循环之前

print Dumper {ABU => $ABU, AB => $AB};
在循环之后,我得到了这个输出:

![在此处输入图片说明] [1]

在人们的回答之后,我意识到问题可能出在我在循环之前将第一个值分配给ABU [1]时:

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

如果我在循环之前使用翻斗车进行打印:

enter image description here

我试图改变第一次的asignation语法:

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

然后Dumper看起来更好:

enter image description here

现在的问题是,我不知道为什么当我运行for循环时,它会在第一行中抱怨:

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

使用此STDERR:

不能使用字符串(&#34; 15&#34;)作为ARRAY参考,而#34; strict refs&#34;

2 个答案:

答案 0 :(得分:3)

问题在于这一行

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

这里你清楚地插入了对数组的引用。您的问题中会遗漏print Dumper {ABU => $ABU, AB => $AB};的结果。但是可以在下一张图片中看到。

image

$VAR->{ABU}[1][0]。经过几个循环后,您将最终获得对同一阵列的多个引用。

对于您的数据格式,您可以

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

但是使用一些克隆程序会更加健壮(不受随着时间的推移而不可避免地出现的功能代码变化的影响)。

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

BTW你的代码可以写成

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

修改

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

$AB->[1][$i]是数组引用

@{$AB->[1][$i]}是由$AB->[1][$i]

引用的数组的内容

[@{$AB->[1][$i]}]是对新数组的数组引用,其中包含$AB->[1][$i]引用的数组内容。它是简写:

do {
    my @array;                # fresh new array
    @array = @{$AB->[1][$i]}; # Here you copy content of array
    \@array;                  # return reference to the new array
}

然后将其推送到$ABU->[1]引用的数组。在此语句之后$ABU->[1][-1]包含对新数组的数组引用,其内容从$AB->[1][$i]引用的数组中复制。

相比之下push @{$ABU->[1]}, $AB->[1][$i];

$AB->[1][$i]是数组引用

您将其推入$ABU->[1]引用的数组中。因此,您推送引用原始数组的数组引用。换句话说,在语句$ABU->[1][-1] = $AB->[1][$i]之后,相同的数组引用。

第三个语句push @{$ABU->[1]}, @{$AB->[1][$i]};将推送$AB->[1][$i]引用的数组内容。这意味着您不会向$ABU->[1]引用的数组添加一个新元素,但会包含与@{$AB->[1][$i]}相同数量的元素。它打破了参考,但没有做你想要的。你可以这样修理它:

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

但写作push @{$ABU->[1]}, [@{$AB->[1][$i]}];的方式并不那么优雅。

答案 1 :(得分:1)

你没有展示如此多的代码。也许$ ABU和$ AB都是对同一个数组的引用。