Trova la dimensione di un array in Perl


243

Mi sembra di aver trovato diversi modi per trovare le dimensioni di un array. Qual è la differenza tra questi tre metodi?

my @arr = (2);
print scalar @arr; # First way to print array size

print $#arr; # Second way to print array size

my $arrSize = @arr;
print $arrSize; # Third way to print array size

13
altri modi: print 0+@arr, print "".@arr,print ~~@arr
mob

3
@mob, ronzio, si potrebbe voler evitare "".@arrcome "@arr"fa qualcosa di completamente diverso.
ikegami,

39
Il "secondo modo" NON è un modo per stampare le dimensioni dell'array ...
tadmc,

in contesto scalare; @arr restituisce le dimensioni della tabella. $ x = @ arr è un contesto scalare. $ # arr restituisce l'ultimo indice dell'array. indicizzazione a partire da 0, quindi equazione vera $ # arr + 1 == @arr. Se si scrive un elemento fuori ordine, ad esempio $ arr [100] = 'any', la tabella viene automaticamente aumentata all'indice massimo 100 e (incluso l'indice 0) a 101 elementi.
Znik,

Risposte:


234

Il primo e il terzo modo sono gli stessi: valutano un array in un contesto scalare. Considererei questo come il modo standard per ottenere le dimensioni di un array.

Il secondo modo in realtà restituisce l'ultimo indice dell'array, che non è (di solito) uguale alla dimensione dell'array.


29
La dimensione di (1,2,3) è 3 e gli indici sono (per impostazione predefinita) 0, 1 e 2. Quindi, $ # arr sarà 2 in questo caso, non 3.
Nate CK

5
La variabile predefinita $[specifica "L'indice del primo elemento in un array e del primo carattere in una sottostringa" ( perldoc perlvar). È impostato su 0 per impostazione predefinita e impostarlo su un valore diverso da 0 è altamente sconsigliato.
Keith Thompson,

5
@Keith Thompson, $[è scoraggiato (ed è stato per un decennio). $[è deprecato. L'uso $[emette un avviso di deprecazione anche quando non si attivano gli avvisi. Assegnare qualsiasi cosa diversa da zero $[sarà un errore in 5.16. Possiamo smettere di menzionare $[già?
ikegami,

2
@Keith Thompson, più vecchio di 5.14, in realtà. Ma come ho detto, è stato scoraggiato e deprecato per molto più tempo di quello, e qualcuno che usa ne $[sarebbe a conoscenza dei suoi effetti.
ikegami,

7
@ikegami: Sì, ma qualcuno sta cercando di capire la differenza tra scalar @arre $#arrdovrebbe ancora capire i possibili effetti $[, per quanto rari lo siano.
Keith Thompson,

41

Primo, il secondo non è equivalente agli altri due. $#arrayrestituisce l'ultimo indice dell'array, che è uno in meno della dimensione dell'array.

Gli altri due sono praticamente uguali. Stai semplicemente usando due modi diversi per creare un contesto scalare. Si tratta di una questione di leggibilità.

Personalmente preferisco quanto segue:

say 0+@array;          # Represent @array as a number

Lo trovo più chiaro di

say scalar(@array);    # Represent @array as a scalar

e

my $size = @array;
say $size;

Quest'ultimo sembra abbastanza chiaro da solo in questo modo, ma trovo che la riga aggiuntiva toglie chiarezza quando fa parte di un altro codice. È utile per insegnare cosa @arrayfa in un contesto scalare e forse se vuoi usarlo $sizepiù di una volta.


15
Personalmente preferisco la versione che utilizza la parola chiave "scalare", perché è abbastanza esplicito che sta forzando un contesto scalare. my $size=@arraysembra che potrebbe essere un errore in cui è stato utilizzato il sigillo sbagliato.
Nate CK,

5
È una pessima idea. Le persone che usano scalarsenza motivo imparano la lezione sbagliata. Cominciano a pensare che gli operatori restituiscono elenchi che possono essere forzati in scalari. L'ho visto decine di volte.
ikegami,

2
Perché questo "nessun motivo"? Stai usando scalarperché stai costringendo la lista a un contesto scalare. Questo è il motivo giusto per usarlo. Il tuo esempio fa esattamente la stessa cosa, ma si basa su ciò che Perl fa quando valuta una variabile di elenco in un contesto implicitamente scalare. Pertanto, il tuo esempio richiede al lettore di conoscere il comportamento implicito di Perl in quel contesto. Stai solo aggiungendo un ulteriore livello di comportamento implicito all'espressione e Perl ha già un comportamento troppo implicito che devi ragionare per decifrare un programma.
Nate CK,

2
@Nate CK, Re "Perché questo" non c'è motivo "? Stai usando scalarperché stai costringendo la lista a un contesto scalare", Hai dimostrato il mio punto sull'apprendimento della lezione sbagliata. Questo è completamente falso. Nessun elenco è mai stato forzato da scalar. (Se lo facesse, scalar(@array)e scalar(@array[0..$#array])restituirebbe la stessa cosa.) scalar(@array)Dice @arraydi restituire uno scalare, che gli hai già detto di fare my $size=.
ikegami,

2
Che ci crediate o no, gli sviluppatori devono eseguire il debug del codice scritto da altri sviluppatori. E gli sviluppatori devono eseguire il debug del codice che hanno scritto tre anni fa.
Nate CK,

27

Ciò ottiene la dimensione forzando l'array in un contesto scalare, in cui viene valutato come dimensione:

print scalar @arr;

Questo è un altro modo per forzare l'array in un contesto scalare, poiché viene assegnato a una variabile scalare:

my $arrSize = @arr;

Questo ottiene l'indice dell'ultimo elemento dell'array, quindi in realtà è la dimensione meno 1 (supponendo che gli indici inizino da 0, che è regolabile in Perl anche se farlo di solito è una cattiva idea):

print $#arr;

Quest'ultimo non è davvero buono da usare per ottenere le dimensioni dell'array. Sarebbe utile se vuoi solo ottenere l'ultimo elemento dell'array:

my $lastElement = $arr[$#arr];

Inoltre, come puoi vedere qui su Stack Overflow, questo costrutto non è gestito correttamente dalla maggior parte degli evidenziatori della sintassi ...


2
Un sidenote: basta usare $arr[-1]per ottenere l'ultimo elemento. E $arr[-2]per ottenere il penultimo, e così via.
tuomassalo,

1
@tuomassalo: sono d'accordo che il tuo suggerimento è un approccio migliore. In retrospettiva, $#arrnon è una funzione molto utile e non è un caso che altre lingue non ne abbiano.
Nate CK,

6

Per usare il secondo modo, aggiungi 1:

print $#arr + 1; # Second way to print array size

for [0..$#array] { print $array[$_ ] } funziona davvero bene anche se lo scopo di ottenere il numero di elementi è di scorrere attraverso l'array. Il vantaggio è che ottieni l'elemento e un contatore che sono allineati.
Westrock,

5

Tutti e tre danno lo stesso risultato se modifichiamo un po 'il secondo:

my @arr = (2, 4, 8, 10);

print "First result:\n";
print scalar @arr; 

print "\n\nSecond result:\n";
print $#arr + 1; # Shift numeration with +1 as it shows last index that starts with 0.

print "\n\nThird result:\n";
my $arrSize = @arr;
print $arrSize;

5
È qualcosa di diverso da ciò che è già stato menzionato in questa risposta e in questa ?
Devnull,

5

Esempio:

my @a = (undef, undef);
my $size = @a;

warn "Size: " . $#a;   # Size: 1. It's not the size
warn "Size: " . $size; # Size: 2

2

La sezione "Tipi di variabili Perl" della documentazione perlintro contiene

La variabile speciale $#arrayindica l'indice dell'ultimo elemento di un array:

print $mixed[$#mixed];       # last element, prints 1.23

Potresti essere tentato di utilizzare $#array + 1per dirti quanti elementi ci sono in un array. Non preoccuparti. Come succede, usando @arraydove Perl si aspetta di trovare un valore scalare ("in contesto scalare") ti darà il numero di elementi nell'array:

if (@animals < 5) { ... }

La documentazione perldata tratta anche questo nella sezione "Valori scalari" .

Se si valuta un array in un contesto scalare, restituisce la lunghezza dell'array. (Si noti che ciò non vale per gli elenchi, che restituiscono l'ultimo valore, come l'operatore virgola C, né per le funzioni integrate, che restituiscono qualunque cosa si desideri restituire.) È sempre vero quanto segue:

scalar(@whatever) == $#whatever + 1;

Alcuni programmatori scelgono di utilizzare una conversione esplicita per non lasciare dubbi:

$element_count = scalar(@whatever);

Precedentemente nella stessa sezione viene illustrato come ottenere l'indice dell'ultimo elemento di un array.

La lunghezza di un array è un valore scalare. È possibile trovare la lunghezza dell'array @daysvalutando $#days, come in csh. Tuttavia, questa non è la lunghezza dell'array; è il pedice dell'ultimo elemento, che ha un valore diverso poiché di solito c'è un 0 ° elemento.


2

Esistono vari modi per stampare le dimensioni dell'array. Ecco i significati di tutti: diciamo che il nostro array èmy @arr = (3,4);

Metodo 1: scalare

Questo è il modo giusto per ottenere dimensioni delle matrici.

print scalar @arr;  # prints size, here 2

Metodo 2: numero indice

$#arrfornisce l'ultimo indice di un array. quindi se la matrice ha dimensioni 10, il suo ultimo indice sarebbe 9.

print $#arr;     # prints 1, as last index is 1
print $#arr + 1; # Add 1 to last index to get array size

Stiamo aggiungendo 1 qui considerando l'array come 0-indicizzato . Ma, se non è basato su zero, questa logica fallirà .

perl -le 'local $[ = 4; my @arr=(3,4); print $#arr + 1;'   # prints 6

L'esempio sopra stampa 6, perché abbiamo impostato il suo indice iniziale su 4. Ora l'indice sarebbe 5 e 6, con gli elementi 3 e 4 rispettivamente.

Metodo 3:

Quando una matrice viene utilizzata in un contesto scalare, restituisce la dimensione della matrice

my $size = @arr;
print $size;   # prints size, here 2

In realtà il metodo 3 e il metodo 1 sono uguali.


2

Da perldoc perldata , che dovrebbe essere sicuro di citare:

Quanto segue è sempre vero:

scalar(@whatever) == $#whatever + 1;

Fintanto che non $ $ qualunque ++ e aumenti misteriosamente la dimensione o l'array.

Gli indici dell'array iniziano con 0.

e

È possibile troncare un array fino a zero assegnando ad esso l'elenco null (). Sono equivalenti:

    @whatever = ();
    $#whatever = -1;

Il che mi porta a quello che stavo cercando, ovvero come rilevare l'array è vuoto. L'ho trovato se $ # vuoto == -1;


1

Che dire int(@array)in quanto minaccia l'argomento come scalare.


0

Per trovare la dimensione di un array utilizzare la scalarparola chiave:

print scalar @array;

Per scoprire l'ultimo indice di un array c'è $#(variabile di default Perl). Fornisce l'ultimo indice di un array. Quando una matrice inizia da 0, otteniamo la dimensione della matrice aggiungendone una a $#:

print "$#array+1";

Esempio:

my @a = qw(1 3 5);
print scalar @a, "\n";
print $#a+1, "\n";

Produzione:

3

3
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.