Arrays 对数组的修改也会更改其他数组
我在Perl中有两个全局多维数组Arrays 对数组的修改也会更改其他数组,arrays,perl,subroutine,Arrays,Perl,Subroutine,我在Perl中有两个全局多维数组@p和@p0e。这是遗传算法的一部分,我想将某些密钥从@p保存到@p0e。然后对@p进行修改。有几个子程序可以对@p进行修改,但是有一个子程序有时(不是每次迭代)对@p的修改也会导致@p0e被修改(它接收相同的键),尽管@p0e不应该受到影响 # this is the sub where part of @p is copied to @p0e sub saveElite { @p0e = (); my $i = 0; foreach my $
@p
和@p0e
。这是遗传算法的一部分,我想将某些密钥从@p
保存到@p0e
。然后对@p
进行修改。有几个子程序可以对@p
进行修改,但是有一个子程序有时(不是每次迭代)对@p
的修改也会导致@p0e
被修改(它接收相同的键),尽管@p0e
不应该受到影响
# this is the sub where part of @p is copied to @p0e
sub saveElite {
@p0e = (); my $i = 0;
foreach my $r (sort({$a<=>$b} keys $f{"rank"})) {
if ($i<$elN) {
$p0e[$i] = $p[$f{"rank"}{$r}]; # save chromosome
}
else {last;}
$i++;
}
}
# this is the sub that then sometimes changes @p0e
sub mutation {
for (my $i=0; $i<@p; $i++) {
for (my $j=0; $j<@{$p[$i]}; $j++) {
if (rand(1)<=$mut) { # mutation
$p[$i][$j] = mutate($p[$i][$j]);
}
}
}
}
#这是将@p的一部分复制到@p0e的子节点
亚储蓄精英{
@p0e=();我的$i=0;
foreach my$r(排序({$a$b}键$f{“rank”})){
如果($i这是因为它是一个数组数组。第一级数组只存储对内部数组的引用,如果修改内部数组,它在两个数组中都会更改-它们都引用同一个数组。深层副本而不是创建浅层副本。这是因为它是一个数组数组。第一级数组只存储引用对于内部数组,如果修改内部数组,它在两个数组中都会发生更改-它们都引用同一个数组。深度副本而不是创建浅层副本。我认为您的问题可能是:
因为它看起来像是一个多维数组
问题是,perl“处理”多维数组的方式是通过引用数组。因此,如果复制内部数组,则通过引用执行
例如:
您将看到,通过更改@list
中的元素,我们还可以修改@other_list
——如果我们只是打印它们,我们会得到:
List:
ARRAY(0x2ea384)
ARRAY(0x12cef34)
ARRAY(0x12cf024)
Other List:
ARRAY(0x2ea384)
ARRAY(0x12cef34)
注意重复的数字-这意味着你有相同的参考
解决这一问题的最简单方法是公正地使用[]
:
push ( @other_list, [@{$list[0]}], [@{$list[1]}] ); #make a sub list of two rows;
然后,这将插入包含列表中取消引用元素的匿名数组(新数组)
尽管如此,我们仍在努力-请打开strict
和warnings
。从长远来看,它们将为您节省很多痛苦。我认为您的问题可能是:
$j = $f{"rank"}{$r};
$p0e[$i] = $p[$j];
因为它看起来像是一个多维数组
问题是,perl“处理”多维数组的方式是通过引用数组。因此,如果复制内部数组,则通过引用执行
例如:
您将看到,通过更改@list
中的元素,我们还可以修改@other_list
——如果我们只是打印它们,我们会得到:
List:
ARRAY(0x2ea384)
ARRAY(0x12cef34)
ARRAY(0x12cf024)
Other List:
ARRAY(0x2ea384)
ARRAY(0x12cef34)
注意重复的数字-这意味着你有相同的参考
解决这一问题的最简单方法是公正地使用[]
:
push ( @other_list, [@{$list[0]}], [@{$list[1]}] ); #make a sub list of two rows;
然后,这将插入包含列表中取消引用元素的匿名数组(新数组)
尽管如此,我们仍在努力-请打开strict
和warnings
。从长远来看,它们将为您节省很多痛苦
$j = $f{"rank"}{$r};
$p0e[$i] = $p[$j];
$p[$j]
是一个数组引用,您可以将其视为指向特定内存地址处的特定数据列表。对$p0e[$i]
的赋值还告诉Perl让$i
的@p0e
第四行也引用相同的内存块。因此,当您以后更改$p0e[$i][$k]
,您会发现,$p[$j][$k]
的值也发生了变化
要解决此问题,您需要分配$p[$j]
的副本。以下是一种方法:
$p0e[$i] = [ @{$p[$j]} ];
@{$p[$j]}
区分数组引用,并且[…]
为其创建一个新引用,因此在此语句之后,$p0e[$i]
将具有与$p[$j]
相同值的内容,但指向不同的内存块
$p[$j]
是一个数组引用,您可以将其视为指向特定内存地址处的特定数据列表。对$p0e[$i]
的赋值还告诉Perl让$i
的@p0e
第四行也引用相同的内存块。因此,当您以后更改$p0e[$i][$k]
,您会发现,$p[$j][$k]
的值也发生了变化
要解决此问题,您需要分配$p[$j]
的副本。以下是一种方法:
$p0e[$i] = [ @{$p[$j]} ];
@{$p[$j]}
区分数组引用,并且[…]
为其创建一个新引用,因此在此语句之后,$p0e[$i]
将具有与$p[$j]相同值的相同内容
但指向另一个内存块。这将从一些示例数据中受益。使用严格的和警告
。事实上,很难判断您引用的这段代码中是否存在问题,因为它很容易不存在。这将从一些示例数据中受益。而且使用strict
和warnings
。事实上,很难判断您引用的这段代码中是否存在问题,因为它很容易就不存在了。