2011-07-03 16 views
5

mogę utworzyć tablicę z „pustych gniazd” w nim:Jak utworzyć anonimową tablicę ([]) z "pustymi gniazdami"?

$ perl -wde 1 
... 
    DB<1> $x[2] = 0 
    DB<2> x \@x 
0 ARRAY(0x103d5768) 
    0 empty slot 
    1 empty slot 
    2 0 

lub

DB<3> $#y = 4 
    DB<4> x \@y 
0 ARRAY(0x103d5718) 
    0 empty slot 
    1 empty slot 
    2 empty slot 
    3 empty slot 
    4 empty slot 

Uwaga: to nie jest taka sama jak przypisywanie undef.

Ale jak to określić dla anonimowej tablicy przy użyciu [ i ]?

To nie zadziała:

DB<5> x [,,0] 
syntax error at (eval 27)[/usr/local/lib/perl5/5.10.0/perl5db.pl:638] line 2, near "[," 

I to nie zbyt, bo tylko dostać przypisaną wartość:

DB<6> x []->[2] = 0 
0 0 

Bonus pytanie: w jaki sposób mogę sprawdzić na 'gniazda pustą tablicę' w moim skrypcie Perla?

Tło: W moich skryptach testowych chciałbym móc dokładnie porównać zawartość tablicy. Na przykład chcę odróżnić "nieprzypisane" i "przypisane wartością niezdefiniowaną".

Dzięki za wszelkie spostrzeżenia.

+1

To znaczy, jak to zrobić bezpośrednie przypisanie do tablicy, korzystając '[]' dla anonimowej tablicy, posiadającej wartości wewnątrz tablicy, które zwracają fałsz podczas testowania z 'exist'? – TLP

+0

Tak. Będąc leniwym, byłoby miło móc to określić w jednym komunikacie. W przeciwnym razie muszę użyć "undef" lub zrobić to w wielu instrukcjach. – hexcoder

Odpowiedz

5
use feature qw/ say /; 
use strict; 
use warnings; 

my $aref; 

$#{$aref} = 4; 
$aref->[2] = undef; 
$aref->[3] = ''; 

foreach my $idx (0 .. $#{$aref}) { 
    say "Testing $idx."; 
    say "\t$idx exists." if exists $aref->[$idx]; 
    say "\t$idx defined." if defined $aref->[$idx]; 
} 

OUTPUT: 
Testing 0. 
Testing 1. 
Testing 2. 
    2 exists. 
Testing 3. 
    3 exists. 
    3 defined. 
Testing 4. 

Wstępnie przydzieliliśmy pięć miejsc w anonimowej tablicy, @{$aref}. Najwyższy indeks to 4. Jesteśmy w stanie ustalić, jaki jest najwyższy indeks w ten sam sposób, w jaki go stworzyliśmy; testując wartość $#{$aref}. Możemy przetestować istnienie. Wiemy, że wszystko pomiędzy 0 i 4 zostało utworzone. Ale Perl zgłasza tylko "istnieje" dla elementów tablicy, które konkretnie miały coś do nich przypisanego (nawet jeśli jest to undef). Dlatego zgłoszono, że istnieje $aref->[2], ale nie jest zdefiniowany. Dla zabawy, przypisaliśmy '' do $aref->[3], aby zobaczyć raport testowy zdefiniowany raz.Krótko mówiąc, mimo że macierz jest wstępnie rozszerzona, możemy przetestować różnicę między elementem zainicjowanym za pomocą undef, a elementem będącym undef poprzez wstępne rozszerzenie tablicy, używając "exists".

Nie mogę powiedzieć, że to udokumentowane zachowanie exists. Więc nie ma gwarancji, że pewnego dnia się nie zmieni. Ale działa na 5.8, 5.10, 5.12 i 5.14.

Więc szuka prosty sposób wybrać, które elementy zostały zainicjowany, które zostały zdefiniowane, a które nie, oto przykład:

use feature qw/ say /; 
use strict; 
use warnings; 

my $aref; 

$#{$aref} = 4; 
$aref->[2] = undef; 
$aref->[3] = ''; 

my @initialized = grep { exists $aref->[$_] } 0 .. $#{$aref}; 
my @defined = grep { defined $aref->[$_] } 0 .. $#{$aref}; 
my @uninitialized = grep { not exists $aref->[$_] } 0 .. $#{$aref}; 
my @init_undef = grep { exists $aref->[$_] and not defined $aref->[$_] } 0 .. $#{$aref}; 
say "Top index is $#{$aref}."; 
say "These elements are initialized: @initialized."; 
say "These elements are not initialized: @uninitialized."; 
say "These elements were initialized with 'undef': @init_undef."; 
say "These elements are defined: @defined." 
+0

Wielkie dzięki! Świetna odpowiedź na moje drugie pytanie! W międzyczasie dowiedziałem się, że 'delete $ aref -> [2];" zmienia się z powrotem na "nie zainicjalizowane", tak jak ma to miejsce w przypadku wpisów hash. – hexcoder

+0

Cieszę się, że okazało się to pomocne. Zawsze dobrze się pracuje nad tymi zagadkami. – DavidO

-1

Możesz zrobić tylko tego rodzaju rzeczy z kodu XS (patrz na przykład Devel::Peek). Niektóre, ale nie wszystkie, są ujawnione przez pakiety *::Util. (Pracuję na debugowanie/śledzenia pakiet, więc wiem o tym więcej niż ktokolwiek ma potrzeby ....)

+0

Dzięki za wskazówki. Spojrzę na to. Szkoda, nie ma bezpośredniej drogi Perla (i myślałem, że jest więcej niż jeden sposób, aby to zrobić ;-). – hexcoder

+0

Nie mogłem znaleźć niczego przydatnego w * :: Util. Miałem nadzieję na coś na liście :: * Util * lub Array :: Utils, ale nic. Możesz być bardziej dokładny? – hexcoder

3

To powinno zrobić:

$a=[]; 
$#$a=4; 
+0

Zgadzam się, podobnie "$ a = []; $ a -> [2] = 0; 'powinno również działać. Ale czy jest to możliwe w jednym stwierdzeniu? Prawdopodobnie nie bez wsparcia z modułu. – hexcoder

1

Tło: W moim skrypty testowe Chciałbym móc dokładnie porównać zawartość tablicy. Na przykład chcę odróżnić "nieprzypisane" i "przypisane wartością niezdefiniowaną".

Możesz sprawdzić, czy indeks minął koniec. Poza tym niewiele możesz zrobić.

$x = []; 
undef $x->[9999]; 
print scalar @$x; 

drukuje 10000. undef $x->[9999] jest równoważna $x->[9999] = undef; Ponieważ żaden z elementów 0 do 9998 istnieje, Perl będzie magicznie przypisać wszystkie elementy interweniujących do undef.

+0

Dzięki. Nie zgadzam się z tym, że 'perl magicznie przydzieli wszystkie interweniujące elementy do undef'. Jak widzisz, w moich pierwszych wyjściach do debugowania widać "puste gniazdo". Gdyby były __assigned__ 'undef', debugger wyświetli tutaj 'undef'. Próbowałem tego, ale nie pokazałem tego w pytaniu. – hexcoder

+0

@hexcoder: To dlatego, że chociaż ich wartość nie jest zdefiniowana, nie mają one wartości undef. Dziwne niuanse. – DavidO

+0

@DavidO: Tak. w debugerze występuje różnica między 'x @ x' i' x \ @ x'. Pierwszy pokaże 'undef', drugi "pusty slot". Natomiast 'p @ x' daje ostrzeżenia dla niezainicjowanych wartości. – hexcoder