Pourquoi ne puis-je écrire @F [1 ..- 1] pour obtenir des éléments 1..last?
Question
En Perl, le -1
d'index de tableau signifie que le dernier élément:
@F=(1,2,3);
print $F[-1]; # result: 3
Vous pouvez également utiliser la notation $#
à la place, ici $#F
:
@F=(1,2,3);
print $F[$#F]; # result: 3
Alors, pourquoi ne pas -1
et $#F
donnent le même résultat quand je veux spécifier le dernier élément dans une plage:
print @F[1..$#F]; # 23
print @F[1..-1]; # <empty>
Le tableau @F[1..-1]
devrait vraiment contenir tous les éléments de l'élément 1
à la dernière, non?
La solution
Votre problème est la syntaxe @a[b..c]
implique deux opérations distinctes. est évalué en premier b..c
, retournant une liste, puis @a[]
est évaluée avec cette liste. L'opérateur de gamme ..
ne sait pas qu'il est utilisé pour les indices du tableau, donc dans la mesure où il est préoccupé, il n'y a rien entre 1 et -1. Elle retourne la liste vide, de sorte que le tableau renvoie une tranche vide.
Autres conseils
Il n'y a rien de spécial .. dans une tranche de tableau; il génère juste la plage demandée et la tranche de cette plage est recherchée.
@a[-3..-1]
=> @a[-3,-2,-1]
et @a[1..3]
=> @a[1,2,3]
, mais @a[1..-1]
devient @a[()]
.
print join ', ', 1..$#F; # 1, 2, 3, 4, 5, 6, ...
print join ', ', 1..-1; #
La raison est que le « ..
» opérateur n » t faire quelque chose de spécial à l'intérieur d'un indice de tableau.
Dans un contexte de liste, il renvoie une liste de valeurs de comptage (par les) de la valeur de gauche à la juste valeur. Si la valeur de gauche est supérieure à la valeur de droite, elle retourne la liste vide.
$#F
est l'index du dernier élément, qui est la même que la longueur de moins d'une '@F -1
. (Si la longueur est au moins un.)
$F[-1]
est juste un cas particulier, pour le rendre plus facile d'obtenir à des éléments de l'autre extrémité, sans avoir à calculer la position manuellement.
$F[-1] === $F[ @F -1 ] === $F[ $#F ]
@F[ 1 .. (@F -1) ] === @F[ 1 .. $#F ]
@F[ 1 .. (@F -2) ] === @F[ 1 .. ( $#F -1 ) ]
Sachant cela, vous pouvez utiliser des variables dans un opérateur d'intervalle:
use strict;
use warnings;
use feature 'say';
sub list{
my($arr,$first,$last) = @_;
$first = @$arr + $first if $first < 0;
$last = @$arr + $last if $last < 0;
return @$arr[ $first .. $last ];
}
my @F = 1..3;
say join ', ', list(\@F,1,-1)
2, 3
Note: Ceci est un exemple incomplet, il ne fonctionnera pas correctement pour certains cas limites
$ # F est le dernier indice valide de F, et non le nombre d'éléments.
@F = (1,2,3); # Donc $ # F est 2
Les règles sont les suivantes:
- si l'index de matrice est non-négatif (ou, de manière équivalente, supérieure à
$[
), commencer à compter du début de la matrice - si elle est négative, commencez à compter à la fin
- si on leur donne une gamme, retourner une tranche de tableau
Maintenant, tout comme l'ensemble (a, b) est vide si a> b , le 1 .. -1
set est également vide. Par conséquent,
@a[ empty set ]
correspond à une tranche de tableau vide.
L'opérateur [] acceptera soit un seul indice ou une plage.
-1 est acceptée comme index pour désigner l'indice de l'élément précédent. La bonne façon est $ # F.
Une gamme de 1 ..- 1 est vide, et qui est la raison pour laquelle il ne retourne rien, parce que l'évaluation de la gamme est distincte de l'évaluation de l'indice.