2011-07-03 12 views
5

puedo crear una matriz con ranuras vacías '' en él:¿Cómo crear una matriz anónima ([]) con 'espacios vacíos'?

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

o

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 

Tenga en cuenta: esto no es lo mismo que asignar undef.

Pero, ¿cómo especifico eso para una matriz anónima usando [ y ]?

Esto no funcionará:

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

Y esto también falla, ya que solo me dan el valor asignado:

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

Bono pregunta: ¿Cómo puedo comprobar una 'ranura de matriz vacía' en mi script Perl?

Antecedentes: en mis scripts de prueba me gustaría poder comparar los contenidos de la matriz con precisión. Por ejemplo, quiero distinguir entre 'no asignado' y 'asignado con un valor undef'.

Gracias por cualquier idea.

+1

Quieres decir cómo hacer una asignación directa a una matriz, usando '[]' para una matriz anónima, que tiene valores dentro de la matriz que devuelve falso cuando se prueba con 'exists'? – TLP

+0

Sí. Siendo perezoso, sería bueno poder especificar esto en una declaración. De lo contrario, tengo que usar 'undef' o hacerlo en múltiples declaraciones. – hexcoder

Respuesta

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. 

Nos preasignados cinco puntos de la matriz en el anonimato, @{$aref}. El índice superior es 4. Podemos encontrar cuál es el índice superior de la misma manera que lo creamos; probando el valor de $#{$aref}. Podemos probar la existencia. Sabemos que se creó todo entre 0 y 4. Pero Perl solo informa "existe" para los elementos de la matriz que tienen específicamente algo asignado (incluso si es undef). Por lo tanto, se informa que existe $aref->[2], pero no está definido. Solo por diversión, asignamos '' a $aref->[3] para ver un informe de prueba definido una vez.Pero la historia breve es que, aunque la matriz se amplíe previamente, aún podemos probar la diferencia entre un elemento inicializado con undef y un elemento que es undef a través de la preextensión de la matriz, usando 'exists'.

No puedo decir que el comportamiento documentado de exists. Entonces no hay garantía de que no cambie algún día. Pero funciona en 5.8, 5.10, 5.12 y 5.14.

Por lo tanto, en busca de una forma sencilla de encontrar qué elementos se inicializa, que se define, y cuáles no, he aquí un ejemplo:

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

¡Muchas gracias! ¡Gran respuesta para mi segunda pregunta! Mientras tanto, descubrí que 'delete $ aref -> [2];' cambia a 'no inicializado' como lo hace para las entradas hash. – hexcoder

+0

Me alegra que lo haya encontrado útil. Siempre es divertido trabajar en estos rompecabezas. – DavidO

-1

Solo puede hacer ese tipo de cosas desde el código XS (consulte, por ejemplo, Devel::Peek). Algunos, pero no todos, están expuestos en los paquetes *::Util. (He estado trabajando en una depuración/rastreo de paquete, así que sé más de esto que cualquier persona debe necesitar ....)

+0

Gracias por los consejos. Echaré un vistazo. Lástima, no hay una forma directa de Perl (y pensé que había más de una forma de hacerlo ;-). – hexcoder

+0

No pude encontrar nada útil en * :: Util. Esperaba algo en List :: * Util * o Array :: Utils, pero nada. ¿Podría ser más específico? – hexcoder

3

Eso debería hacer:

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

Acepto, del mismo modo '$ a = []; $ a -> [2] = 0; 'debería hacer también. ¿Pero es posible en una declaración? Probablemente no sin ningún soporte de un módulo. – hexcoder

1

Antecedentes: En mi guiones de prueba Me gustaría poder comparar los contenidos de la matriz con precisión. Por ejemplo, quiero distinguir entre 'no asignado' y 'asignado con un valor undef'.

Puede verificar si el índice ha pasado el final. Más allá de eso, no hay mucho que puedas hacer.

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

impresiones 10000. El undef $x->[9999] es equivalente a $x->[9999] = undef; Debido a que ninguno de los elementos de 0 a 9998 existe, Perl mágicamente ceder la totalidad de los elementos que intervienen a undef.

+0

Gracias. No estoy de acuerdo con que 'perl asigne mágicamente todos los elementos intermedios a undef'. Como se puede ver en mi primera depuración, los agujeros de salida se muestran como 'ranura vacía'. Si fueron __asigned__ 'undef', el depurador mostraría 'undef' aquí. Lo intenté, pero no lo mostré en la pregunta. – hexcoder

+0

@hexcoder: Eso es porque aunque su valor no está definido, no tienen undef como valor. Extraño matiz. – DavidO

+0

@DavidO: Sí. en el depurador hay una diferencia entre 'x @ x' y' x \ @ x'. El primero mostrará 'undef', el segundo 'slot vacío'. Y 'p @ x' dará advertencias para los valores no inicializados. – hexcoder

Cuestiones relacionadas