Mam skrót tablic, które są zadeklarowane w następujący sposób:
my %hash;
push @{ $hash{ $value1[$_] } }, [ $value1[$_], $value2[$_], $value3[$_], $value4[$_], $value5[$_] ] for 0 .. $#value1;
Chcę mieć możliwość sprawdzenia wartości dla każdego klucza za pomocą:
open KEYS, ">keys.txt" or die "Can"t write to "keys.txt"n";
for my $key ( sort keys %hash ) {
print KEYS "Key: $key contains the values: ";
for my $value ( @{$hash{$value1}} ) {
print KEYS "$value ";
}
print KEYS "n";
}
close(KEYS);
Chociaż mogę wizualizować klucze i powiązane wartości za pomocą Data :: Dumper, dane wyjściowe z powyższego kodu podają lokalizacje pamięci, a nie wartości dla każdego klucza. Na przykład:
Key: "Value1" contains the values: ARRAY(0x7fcd8645ba68)
Mimo że wypycham tę samą liczbę wartości do każdej tablicy, każdy klucz zawiera inną liczbę wartości
Czy jest coś nie tak ze sposobem, w jaki to robię?
Odpowiedzi:
6 dla odpowiedzi № 1Po pierwsze, masz w swojej wewnętrznej pętli
for my $value ( @{$hash{$value1}} ) {
print KEYS "$value ";
}
Czym na ziemi jest $value1
? Myślę, że chciałeś użyć $key
. Zawsze use strict; use warnings
ostrzegać przed niezdefiniowanymi wartościami i niezadeklarowanymi zmiennymi.
Następnie przyjrzyjmy się, co się stanie, kiedy to zrobimy
my %hash;
push @{ $hash{ $value1[$_] } }, "(value$_)" for 0 .. $#value1;
zamiast tego, tzn. po prostu wpychamy ciąg do tablicyref w haszu. Następnie wynik wygląda trochę jak
Key: Value1 contains the values: (value0)
Key: Value2 contains the values: (value1)
Key: Value3 contains the values: (value2)
Aha! Cokolwiek wpychamy na tę tablicę, jest drukowane tak, jak jest. Jeśli wypchniesz anonimową tablicę, np [...]
, otrzymasz oznaczenie tego odwołania: ARRAY(0x1234567)
.
Prawdopodobnie potrzebujesz zawartości tego arrayref. Łatwe: po prostu odłóż to.
...;
print KEYS "[@$value] ";
czy jakoś tak. The "[...]"
są tutaj używane tylko do wizualnego grupowania wyników.
Uwagi do stylu:
Proszę rozważyć 3-arg open
z leksykalnymi uchwytami plików:
my $filename = "keys.txt";
open my $keys, "<", $filename or die "Can"t open $filename: $!";
lub użyj automatycznej obsługi błędów:
use autodie;
open my $keys, "<", "keys.txt";
Tak czy inaczej, zwykle ważne jest, aby dołączyć powód za porażkę $!
w komunikacie o błędzie lub jest prawie bezużyteczny.
Zamiast używać pętli, kod może być bardziej elegancki map
i join
, w zależności od gustu. Prawdopodobnie zapisałbym pętlę jako
use feature "say";
for my $key ( sort keys %hash ) {
say {$keys} "Key: $key contains the values: "
. join " ", map { "[@$_]" } @{ $hash{$key} };
}
3 dla odpowiedzi № 2
To dlatego, że wypychasz tablicę referencji zamiast listy wartości.
Porównać
push @array, [ $foo ];
do
push @array, $foo;
Obie @array
s zawierają pojedynczy element, ale pierwszy zawiera tablicę zawierającą $foo
, podczas gdy ta ostatnia jest słuszna $foo
.
Jeśli stracisz kwadratowe nawiasy klamrowe po pierwszym push
argument, że będziesz dobrze iść.