我知道这里已经涵盖了类似的主题,但我遇到了一个问题,我认为这是因为我误解了如何在foreach循环的上下文中插入数组切片。我无法弄清楚我哪里出错了,所以我正在寻找一些见解。
我有一个行数可变的二维数组。例如:
@2DArray = (['str1', 1, 2, 'E', val1, val2, val3]
['str2', 3, 4, 'E', val4, val5, val6]
['str4', 5, 6, 'F', val7, val8, val9])
我想构建一个带有附加列的新数组,只有当它们在第3列中包含字符串'E'时才包含原始数组的一些行。另外,对于我希望包含在我的行中的行新数组,我只想要列的一个子集,我希望该子集的顺序不同。最终目标是生成下游脚本所需的正确格式的输出。
我试图这样做:
my $projName = 'test';
my $i = 1;
my @Newarray
my @Newarray_element;
foreach (@2DArray) {
if (${$_}[3] eq 'E') {
${$_}[3] = $i;
${$_}[5] = '+';
@Newarray_element = ("$projName$i", @$_[0,1,2,5,3], 'STR', 11, 11);
$i++;
push (@Newarray, \@Newarray_element);
}
next;
}
print (join("\t", @$_), "\n") for @Newarray;
但是,如果我这样做,我得到的是:
#(original) col nums: 0 1 2 5 3
test2 str2 3 4 + 2 STR 11 11
test2 str2 3 4 + 2 STR 11 11
也就是说,我的新数组对于原始数组中的每一行都有一行,第3列中有一个'E',但是每一行都填充了循环处理的最后一行的值。
我认为问题与在foreach循环中切片2D数组有关的原因是我知道如果我只是循环遍历2D数组,在第3列中找到所有带有'E'的行,修改一些值在这些行的其他列中,然后将其返回到一个新数组,它都完美地工作。也就是说,如果我改为这样做:
my @Newarray;
my $i = 1;
foreach (@2Darray) {
if (${$_}[3] eq "E") {
${$_}[3] = $i;
${$_}[5] = '+';
$i++;
push (@Newarray, \@$_);
}
next;
}
print (join("\t", @$_), "\n") for @Newarray;
我得到了我期望的输出:
* &
str1 1 2 1 val1 + val3
str2 3 4 2 val4 + val6
其中标有*和&的列是修改后的第3列和第5列。让冲击开始:我的新手自己出错了什么?
答案 0 :(得分:4)
变量@Newarray_element
指向整个程序中的相同内存空间,因此您在一次迭代中所做的更改会传播到您在赋值中使用该变量的先前迭代。
两种可能的修复方法:
<强>一即可。更改变量的范围,以便在每次迭代中使用不同的内存。 变化
my @Newarray_element;
foreach (@2DArray) {
...
到
foreach (@2DArray) {
my @Newarray_element;
...
甚至
foreach (@2DArray) {
...
my @Newarray_element = ("$projName$i", @$_[0,1,2,5,3], 'STR', 11, 11);
两个:重用@Newarray_element
,但将其数据的副本分配给@Newarray
的每一行。变化
push (@Newarray, \@Newarray_element);
到
push (@Newarray, [ @Newarray_element ]);
后一个调用创建并附加一个新的匿名数组引用到@Newarray
。