Pregunta

¿Cómo puedo hacer que una matriz más corto en Perl?He leído algunas páginas web que indica que puedo asignar:

$#ARRAY = 42;

He leído que el uso de la $# es obsoleto.Necesito una solución que va a trabajar para una matriz de matrices, demasiado.Esto no funciona:

$#$ARRAY[$i] = 42;
¿Fue útil?

Solución

No estoy al tanto de la asignación de $#ARRAY ser despreciado; perldoc perldata de 5.10.0 ciertamente no dice nada acerca de ella.Es la manera más rápida para truncar una matriz.

Si quieres algo un poco más legible, uso splice:

splice @ARRAY, 43;

(Nota 43 en lugar de 42 - $#ARRAY consigue el último índice de la matriz, mientras que splice taks la longitud de la matriz en su lugar).

Como para trabajar en las matrices de matrices, supongo que te refieres a ser capaz de truncar una matriz anidada a través de una referencia?En ese caso, usted desea:

$#{$ARRAY->[7]} = 42;

o

splice @{$ARRAY->[7]}, 43;

Otros consejos

Sus opciones son casi ilimitadas (yo he descrito cinco enfoques aquí), pero su estrategia será dictada por exactamente cuáles son sus necesidades específicas y los objetivos.(todos los ejemplos se convierta @array no tener más de $N elementos)


[EDITAR]

Como otros han señalado, la forma en que se sugiere en la pregunta original no es realmente obsoleto, y proporciona la forma más rápida, tersest, pero no necesariamente el más legible de la solución. También tiene el efecto secundario de la expansión de una matriz de menos de $N elementos con elementos vacíos:

$#array = $N-1;

Menos código:

#best for trimming down large arrays into small arrays
@array = $array[0..($N-1)];

Más eficiente para el recorte de un número pequeño de una gran variedad:

#This is a little less expensive and clearer
splice(@array, $n, @#array);

Indeseables en casi todos los casos, a menos que usted realmente amor eliminar():

#this is the worst solution yet because it requires resizing after the delete
while($N-1 < $#array)
{
   delete(array[$i]);
}

Útil si usted necesita el resto de la lista en orden inverso:

#this is better than deleting because there is no resize
while($N-1 < $#array)
{
    pop @array;
    #or, "push $array2, pop @array;" for the reverse order remainder
}

Útil para ahorrar tiempo en el largo plazo:

#don't put more values into the array than you actually want

El $# variable está en desuso, pero el $#array no es una función.

El uso de la $#array la sintaxis de una expresión arbitraria que produce una matriz de referencia, hacer $#{ EXPR }.

Ver la inestimable: http://perlmonks.org/?node=References+quick+reference

Esencialmente se dio canónica de la respuesta de usted.Acortar una matriz mediante el establecimiento de los últimos índice:

$#Array = 42

El $#Foo notación para denotar el último índice de la matriz es absolutamente no obsoleto.Del mismo modo, la asignación a no ser en desuso, ya sea.Citando el perldata documentación:

La longitud de una matriz es un valor escalar. Usted puede encontrar la longitud de matriz de @días evaluando $#días, como en csh.Sin embargo, este no es el la longitud de la matriz;es el subíndice del último elemento, que es un valor diferente ya que no es normalmente un elemento 0. La asignación a $#días realmente cambia la longitud de la matriz. El acortamiento de una matriz de esta manera destruye intervenir valores.El alargamiento de una matriz que se previamente acortado no recuperar los valores que se encontraban en esos elementos.(Solía hacerlo en Perl 4, pero tuvimos que romper este a asegúrese de que los destructores se llama cuando se esperaba.)

  • $#matriz es la el último índice de de la matriz.
  • $#$matriz sería el último índice de una matriz señaló por $matriz.
  • $#$array[$i] significa que usted está tratando de índice de un escalar--no se puede hacer.$#{$matriz[3]} correctamente resuelve la suscripción de la matriz principal antes de tratar de referencia el último índice.
  • Utilizado solo

    $#{$matriz[3]} = 9;

    asigna una longitud de 9 a autovivified matriz en $matriz[3].

  • En caso de duda, utilice Data::Dumper:

    use Data::Dumper;
    $#{$array[3]} = 5;
    $#array       = 10;
    print Dumper( \@array, $array ), "\n";
    

$#{$MATRIZ[$i]} = 42;

Usted podría hacer

splice @array, $length;
#or
splice @{$arrays[$i]}, $length;

Hay dos maneras de interpretar la pregunta.

  • Cómo reducir la longitud de la matriz?
  • Cómo reducir la cantidad de memoria consumida por la matriz?

La mayoría de las respuestas que hasta ahora se centran en la antigua.En mi opinión, la mejor respuesta es la empalme la función.Por ejemplo, para quitar 10 elementos desde el final:

splice @array, -10;

Sin embargo, debido a la forma de Perl administra la memoria de matrices, la única manera de garantizar que una matriz consume menos memoria es copiar a un nuevo array (y dejar que la memoria de la antigua matriz será reclamado).Para esto, yo tendería a pensar sobre el uso de un rebanada operación.E. g., para quitar 10 elementos:

@new = @old[ 0 .. $#old - 10 ]

He aquí una comparación de los diferentes enfoques para una de 500 elemento de la matriz (usando 2104 bytes):

  original: length  500 => size 2104
     pound: length  490 => size 2208
    splice: length  490 => size 2104
    delete: length  490 => size 2104
     slice: length  490 => size 2064

Se puede ver que sólo el sector de la operación (se copia en una nueva matriz) tiene un menor tamaño que el original.

Aquí está el código que he usado para este análisis:

use strict;
use warnings;
use 5.010;
use Devel::Size qw/size/;

my @original = (1 .. 500);
show( 'original', \@original );

my @pound = @original;
$#pound = $#pound - 10;
show( 'pound', \@pound );

my @splice = @original;
splice(@splice,-10);
show( 'splice', \@splice);

my @delete = @original;
delete @delete[ -10 .. -1 ];
show( 'delete', \@delete );

my @slice = @original[0 .. $#original - 10];
show( 'slice', \@slice);

sub show {
    my ($name, $ref) = @_;
    printf( "%10s: length %4d => size %d\n", $name, scalar @$ref, size($ref));
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top