简体   繁体   English

修改然后在Perl中切片未知大小的2D数组

[英]Modifying then Slicing 2D Array of Unknown Size in Perl

I know that similar topics have been covered here, but I am running into a problem that I think arises from my misunderstanding how array slices are interpolated in the context of a foreach loop. 我知道这里已经涵盖了类似的主题,但是我遇到了一个问题,我认为这是因为我误解了如何在foreach循环的上下文中插入数组切片。 I can't figure out where I've gone wrong, so I'm looking for some insight. 我无法弄清楚我哪里出错,所以我正在寻找一些见解。

I have a 2D array with a variable number of rows. 我有一个行数可变的二维数组。 For example purposes: 例如:

@2DArray = (['str1', 1, 2, 'E', val1, val2, val3]
            ['str2', 3, 4, 'E', val4, val5, val6]
            ['str4', 5, 6, 'F', val7, val8, val9])   

I want to build a new array, with additional columns, that incorporates some of the rows of the original array only if they contain the string 'E' in column 3. Additionally, for the rows I do wish to incorporate in my new array, I only want a subset of the columns and I want that subset in a different order. 我想构建一个带有附加列的新数组,只有当它们在第3列中包含字符串'E'时才包含原始数组的一些行。另外,对于我希望在我的新数组中包含的行,我只想要列的一个子集,我希望该子集的顺序不同。 The end goal is to generate output of the correct format required by downstream scripts. 最终目标是生成下游脚本所需的正确格式的输出。

Here is my attempt to do that: 这是我尝试这样做的:

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;

However, if I do that, what I get is: 但是,如果我这样做,我得到的是:

#(original) col nums:      0       1    2    5    3

                  test2    str2    3    4    +    2    STR    11    11
                  test2    str2    3    4    +    2    STR    11    11

Ie, my new array will have a row for every row in the original array with an 'E' in column 3, but each row is populated with the values from the last row to be processed by the loop. 也就是说,我的新数组将在原始数组中的每一行都有一行,第3列中带有“E”,但每行都填充了循环处理的最后一行的值。

The reason I think the issue has to do with slicing a 2D array in a foreach loop is that I know if I merely loop through a 2D array, find all the rows with an 'E' in column 3, modify some values in other columns for those rows, and then return that to a new array it all works perfectly. 我认为这个问题与在foreach循环中切片2D数组有关的原因是我知道如果我只是循环遍历2D数组,在第3列中找到所有带有'E'的行,修改其他列中的某些值对于那些行,然后将它返回到一个新的数组,这一切都完美。 That is to say, if I instead do this: 也就是说,如果我这样做:

my @Newarray;
my $i = 1;
foreach (@2Darray) {
    if  (${$_}[3] eq "E") {
        ${$_}[3] = $i;
        ${$_}[5] = '+';
        $i++;
        push (@Newarray, \@$_);
    }
    next;   
}
print (join("\t", @$_), "\n") for @Newarray;

I get exactly the output I would expect: 我得到了我期望的输出:

                  *            &
str1    1    2    1    val1    +    val3
str2    3    4    2    val4    +    val6

where the columns marked by * and & are the modified columns 3 and 5. Let the onslaught begin: where did my newbie self go wrong? 标有*和&的列是修改后的第3列和第5列。让攻击开始:我的新手自己哪里出错了?

The variable @Newarray_element points to the same memory space throughout your program, so changes you make in one iteration are propagated to previous iterations where you used that variable in an assignment. 变量@Newarray_element指向整个程序中的相同内存空间,因此您在一次迭代中所做的更改将传播到先前的迭代中,您在赋值中使用该变量。

Two possible fixes: 两个可能的修复:

One . 一个 Change the scope of the variable so that it uses different memory in each iteration. 更改变量的范围,以便在每次迭代中使用不同的内存。 Change 更改

my @Newarray_element;
foreach (@2DArray) {
    ...

to

foreach (@2DArray) {
    my @Newarray_element;
    ...

or even 甚至

foreach (@2DArray) {
    ...
    my @Newarray_element = ("$projName$i", @$_[0,1,2,5,3], 'STR', 11, 11);

Two : reuse @Newarray_element but assign a copy of its data to each row of @Newarray . :重用@Newarray_element但其数据的副本分配到的每一行@Newarray Change 更改

push (@Newarray, \@Newarray_element);

to

push (@Newarray, [ @Newarray_element ]);

This latter call creates and appends a new, anonymous array reference to @Newarray . 后一个调用创建并向@Newarray添加一个新的匿名数组引用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM