Wiem, że podobne tematy zostały omówione tutaj, ale mam problem, który moim zdaniem wynika z mojego nieporozumienia, jak wycinki tablic są interpolowane w kontekście pętli foreach. Nie mogę się dowiedzieć, gdzie się nie udało, więc szukam wglądu.Modyfikowanie, a następnie Krojenie tablicy dwuwymiarowej nieznanego rozmiaru w Perlu
Mam tablicę 2D ze zmienną liczbą rzędów. Na przykład celach:
@2DArray = (['str1', 1, 2, 'E', val1, val2, val3]
['str2', 3, 4, 'E', val4, val5, val6]
['str4', 5, 6, 'F', val7, val8, val9])
Chcę zbudować nową tablicę, z dodatkowych kolumn, które zawiera kilka rzędów oryginalnej tablicy tylko jeśli zawierają napis „E” w kolumnie 3. Dodatkowo, dla wiersze, które chcę wprowadzić w mojej nowej tablicy, chcę tylko podzbiór kolumn i chcę tego podzbioru w innej kolejności. Celem końcowym jest wygenerowanie danych wyjściowych o właściwym formacie wymaganym przez skrypty niższego szczebla.
Oto moja próba, aby to zrobić:
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;
Jednakże, jeśli to zrobię, to, co pojawia się:
#(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, moja nowa tablica będzie mieć wiersz dla każdego wiersza w oryginalnej tablicy z literą "E" w kolumnie 3, ale każdy wiersz jest wypełniany wartościami z ostatniego wiersza, które mają być przetwarzane przez pętlę.
Powodem, dla którego myślę, że problem związany jest z cięciem tablicy 2D w pętli foreach, jest to, że wiem, że jeśli po prostu przejdę przez tablicę 2D, znajdę wszystkie wiersze z literą "E" w kolumnie 3, zmodyfikuj niektóre wartości w innych kolumnach dla tych wierszy, a następnie zwróć je do nowej tablicy - wszystko działa idealnie. To znaczy, jeśli zamiast tego zrobić:
my @Newarray;
my $i = 1;
foreach (@2Darray) {
if (${$_}[3] eq "E") {
${$_}[3] = $i;
${$_}[5] = '+';
$i++;
push (@Newarray, \@$_);
}
next;
}
print (join("\t", @$_), "\n") for @Newarray;
otrzymuję dokładnie wyjście spodziewałbym:
* &
str1 1 2 1 val1 + val3
str2 3 4 2 val4 + val6
gdzie kolumny oznaczone * i & są zmodyfikowane kolumny 3 i 5. Niech zacznie się atak: skąd mój nowicjusz się nie pomylił?
Dzięki. Bardzo głupi błąd i dowód, że nie opanowałem jeszcze referencji Perla. Czy możesz wytłumaczyć mi w swoim drugim przykładzie, co dokładnie robi [@New_element]? Jeśli czytam to poprawnie, czy tworzy to anonimową tablicę z zawartością @Newarray_element, która jest tracona po zamknięciu pętli? – MCor
@MCor: Tak, '[@Newarray_element]' tworzy anonimową kopię treści '@ Newarray_element' (i zwraca odniesienie do tej kopii), tak aby po nadpisaniu' @ Newarray_element' przy następnej iteracji pętli kopia pozostanie oryginalna treść. (Jednak byłoby IMO znacznie czystsze, aby utworzyć nową lokalną tablicę w każdej iteracji, przenosząc deklarację 'my' wewnątrz pętli.) –
' [...] 'tworzy nowe anonimowe odwołanie do tablicy, które zostanie wypchnięte na '@ Newarray'. Zawartość tej tablicy wskazanej przez to odwołanie będzie kopią rzeczy w '@ Newarray_element'. Ponieważ każdy jest kopią, nie ma znaczenia, czy zmieniasz '@ Newarray_element' za każdym razem w pętli. Ale pierwszą sugestią @ mob jest o wiele jaśniejszy i bardziej idiotyczny sposób na zrobienie tego. Ustalenie zmiennej do wnętrza pętli tworzy za każdym razem * nowy * '\ @ element Newarray'. – friedo