2010-07-27 7 views
6

quería cortar todos menos los cinco primeros elementos de una matriz, por lo que hizo estúpidamente:Perl lenguaje para conseguir un número máximo de elementos de una matriz

@foo = @foo[ 0 .. 4 ]; 

y de corazón elogiado mi propia inteligencia. Pero eso se rompió una vez que @foo terminó con solo tres elementos, porque luego terminé con dos undef s en el extremo, en lugar de una matriz de tres elementos. Así que lo cambié a:

@foo = @foo > 5 ? @foo[ 0 .. 4 ] : @foo; 

Esto funciona, pero es un poco feo. ¿Hay una mejor expresión idiomática para decir "dame todo hasta los primeros cinco elementos de la matriz"?

+0

¿Es solo porque no soy un hablante nativo de inglés que el título de la pregunta me parece bastante insatisfactorio? Espero que los lectores rápidos (incluido Google) obtengan esto como "Idioma de Perl para obtener el número máximo de una matriz" – Wolf

Respuesta

8

puede establecer el último índice de una matriz para acortar o alargar. Al igual que su código, deberá verificar para asegurarse de que no está creando elementos undef.

$#foo = 4 if $#foo > 4; 
+0

¡Interesante toma esto! No estoy seguro de que me guste más que 'splice()', pero me gusta que sea único. –

+0

¡Me había olvidado de eso! :) +1 – Axeman

+0

Impresionante. Realmente me gusta esta. – friedo

6

Si no se preocupan por mutaciones (implícito en la izda autorreferenciales @foo = algo referencia @foo) utiliza los dos argumento splice(), ver perldoc -f splice para obtener más información.

empalme ARRAY, OFFSET

Elimina los elementos designados por el desplazamiento y la longitud de una matriz, y los reemplaza con los elementos de la lista, si los hubiere. En el contexto de la lista, devuelve los elementos eliminados de la matriz. En contexto escalar, devuelve el último elemento eliminado, o "undef" si no se eliminan elementos. La matriz crece o se reduce según sea necesario. Si OFFSET es negativo, comienza tan lejos del final de la matriz. Si se omite LONGITUD, se elimina todo desde OFFSET en adelante. Si LENGTH es negativo, quita los elementos de OFFSET en adelante a excepción de los elementos -LENGTH al final de la matriz. Si se omiten tanto OFFSET como LENGTH, se elimina todo. Si OFFSET está más allá del final de la matriz, perl emite una advertencia y empalma al final de la matriz.

A continuación, ver el efecto:

@_ = 1..10; 
splice @_, 5; 
say for @_; 


@_ = 1..3; 
splice @_, 5; 
say for @_; 

Si está utilizando warnings, y espero que tendrá que comprobar si la longitud (como en la sugerencia de Axeman) o desactivar la alarma ruidosa (splice() de compensación al final del extremo de la matriz):

{ 
    no warnings 'misc'; 
    splice @_, 5; 
} 
+0

Siempre me olvido de 'empalme' – friedo

+0

Sí, parece algo circular hacer' @foo = @foo [cosas ; ] ', el empalme será masivamente más rápido. –

+0

Desafortunadamente, esto produce la advertencia "empalme() offset pasado fin de matriz", por lo que es posible que desee agregar un 'local $ SIG {__ WARN __}' cuando hace esto, o hacer una verificación de longitud como dijo Axeman. – Ether

1

esto no es tan elegante, pero se puede expresar así:

@foo[ 0..($#foo > 4 ? 4 : $#foo) ]; 

Una función generalizada de min podría verse mejor.

use List::Util qw<min>;  
@foo[ 0..min($#foo, 4) ]; 

Pero si sólo quiere deshacerse de todo lo demás a continuación, sólo tiene que splice fuera el resto:

splice(@foo, 5) if 5 < @foo; 
6

embargo, otra forma:

@foo = splice(@foo, 0, 5); 

A diferencia de la otra sugerencia para empalme, esto no desencadena una advertencia; el 5 explícitamente significa "hasta 5".

+0

expresión más explícita de lo que se quiere [empalme - perldoc.perl.org] (https://perldoc.perl.org/functions/splice.html) también es la solución más corta del punto de vista psicológico;) – Wolf

Cuestiones relacionadas