2010-07-27 6 views
6

je voulais couper tous, mais les cinq premiers éléments d'un tableau, donc je bêtement fait:langage Perl pour obtenir un maximum d'éléments dans un tableau

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

et de bon cœur loué mon propre intelligence. Mais cela a cassé une fois que @foo s'est retrouvé avec seulement trois éléments, parce que je me suis retrouvé avec deux undef s à la fin, au lieu d'un tableau à trois éléments. Donc je l'ai changé pour:

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

Cela fonctionne mais est moche. Y a-t-il un meilleur idiome pour dire «donnez-moi tout jusqu'aux cinq premiers éléments du tableau?

+0

Est-ce que c'est uniquement parce que je ne suis pas un locuteur natif anglais que je trouve le titre de la question assez insatisfaisant? Je m'attends à ce que les lecteurs rapides (y compris Google) obtiennent ceci comme "idiome de Perl pour obtenir le nombre maximum d'un tableau" – Wolf

Répondre

8

Vous pouvez définir le dernier indice d'un tableau pour raccourcir ou allonger. Comme votre code, vous devrez vérifier que vous ne créez pas d'éléments undef.

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

Intéressant prendre cela !! Je ne suis pas sûr que je l'aime plus que 'splice() ', mais j'aime vraiment que c'est unique. –

+0

J'avais oublié ça! :) +1 – Axeman

+0

Génial. J'aime vraiment celle-ci. – friedo

6

Si vous ne se soucient pas de mutations (sous-entendu par les LHS auto-référentiel @foo = quelque chose référence @foo) utiliser les deux arguments splice(), voir perldoc -f splice pour plus d'informations.

épissures MATRICE, OFFSET

supprime les éléments désignés par OFFSET et LONGUEUR d'un tableau, et les remplace par les éléments de la liste, le cas échéant. Dans le contexte de la liste, renvoie les éléments supprimés du tableau. Dans un contexte scalaire, renvoie le dernier élément supprimé, ou "undef" si aucun élément n'est supprimé. Le tableau se développe ou se rétrécit si nécessaire. Si OFFSET est négatif, il commence alors loin de la fin du tableau. Si LENGTH est omis, supprime tout de OFFSET. Si LONGUEUR est négatif, supprime les éléments de OFFSET, sauf pour les éléments -LENGTH à la fin du tableau. Si OFFSET et LENGTH sont omis, tout est supprimé. Si OFFSET a dépassé la fin du tableau, perl émet un avertissement et épissure à la fin du tableau.

Ensuite, regardez l'effet:

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


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

Si vous utilisez warnings, et j'espère que vous devrez vérifier la longueur (comme dans la suggestion de Axeman) ou désactiver l'avertissement bruyant (épissure() end dernier décalage du tableau):

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

J'oublie toujours de 'splice' – friedo

+0

Oui, il semble plutôt circulaire de faire' @foo = @foo [trucs ; ] ', l'épissure sera massivement plus rapide. –

+0

Malheureusement, cela produit l'avertissement "splice() offset après la fin du tableau", vous pouvez donc ajouter un 'local $ SIG {__ WARN __}' lorsque vous faites cela, ou faire une vérification de longueur comme l'a dit Axeman. – Ether

1

ce n'est pas gracieuse, mais vous pouvez l'exprimer comme ceci:

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

Une fonction généralisée min peut être améliorée.

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

Mais si vous voulez juste pour se débarrasser de tout le reste, vous avez juste besoin de splice hors du reste:

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

Encore une autre façon:

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

Contrairement à l'autre suggestion pour épissures, cela ne déclenche pas un avertissement; le 5 signifie explicitement "jusqu'à 5".

+0

expression la plus explicite de ce qui est recherché [splice - perldoc.perl.org] (https://perldoc.perl.org/functions/splice.html) c'est aussi la solution la plus courte du POV psychologique;) – Wolf

Questions connexes