Finden Sie die Größe eines Arrays in Perl

243

Ich habe anscheinend verschiedene Möglichkeiten gefunden, um die Größe eines Arrays zu ermitteln. Was ist der Unterschied zwischen diesen drei Methoden?

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
David
quelle
13
andere Wege: print 0+@arr, print "".@arr,print ~~@arr
Mob
3
@mob, Brummen, könnte man vermeiden wollen, "".@arrso "@arr"tut etwas ganz anderes.
Ikegami
39
Der "zweite Weg" ist NICHT ein Weg, um die Array-Größe zu drucken ...
tadmc
im skalaren Kontext gibt @arr die Tabellengröße zurück. $ x = @ arr ist ein skalarer Kontext. $ # arr gibt den letzten Index des Arrays zurück. Indizierung ab 0, dann ist wahre Gleichung $ # arr + 1 == @arr. Wenn Sie ein Element außerhalb der Reihenfolge schreiben, z. B. $ arr [100] = 'any', wird die Tabelle automatisch auf den maximalen Index 100 und (einschließlich Index 0) auf 101 Elemente erhöht.
Znik

Antworten:

234

Der erste und der dritte Weg sind die gleichen: Sie werten ein Array im skalaren Kontext aus. Ich würde dies als Standardmethode betrachten, um die Größe eines Arrays zu ermitteln.

Der zweite Weg gibt tatsächlich den letzten Index des Arrays zurück, der (normalerweise) nicht der Arraygröße entspricht.

Chris Jester-Young
quelle
29
Die Größe von (1,2,3) ist 3, und die Indizes sind (standardmäßig) 0, 1 und 2. In diesem Fall ist $ # arr also 2, nicht 3.
Nate CK
5
Die vordefinierte Variable $[gibt "Der Index des ersten Elements in einem Array und des ersten Zeichens in einem Teilstring" ( perldoc perlvar) an. Es ist standardmäßig auf 0 gesetzt, und es wird dringend davon abgeraten, etwas anderes als 0 zu setzen.
Keith Thompson
5
@ Keith Thompson, $[ist entmutigt (und seit einem Jahrzehnt). $[ist veraltet. Bei der Verwendung wird $[eine Verfallswarnung ausgegeben, auch wenn keine Warnungen aktiviert sind. Das Zuweisen von etwas anderem als Null $[ist in 5.16 ein Fehler. Können wir schon aufhören zu erwähnen $[?
Ikegami
2
@ Keith Thompson, älter als 5,14, eigentlich. Aber wie gesagt, es ist schon viel länger entmutigt und veraltet, und jemand, der es benutzt, $[würde von seinen Auswirkungen wissen.
Ikegami
7
@ikegami: Ja, aber jemand versucht , den Unterschied zwischen zu verstehen scalar @arrund $#arrsollte noch die möglichen Auswirkungen verstehen $[, selten , obwohl sie sind.
Keith Thompson
41

Erstens ist die zweite nicht gleichbedeutend mit den beiden anderen. $#arrayGibt den letzten Index des Arrays zurück, der um eins kleiner als die Größe des Arrays ist.

Die anderen beiden sind praktisch gleich. Sie verwenden einfach zwei verschiedene Mittel, um einen skalaren Kontext zu erstellen. Es kommt auf die Lesbarkeit an.

Ich persönlich bevorzuge Folgendes:

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

Ich finde es klarer als

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

und

my $size = @array;
say $size;

Letzteres sieht allein so ziemlich klar aus, aber ich finde, dass die zusätzliche Zeile die Klarheit beeinträchtigt, wenn sie Teil eines anderen Codes ist. Es ist nützlich, um zu lehren, was @arrayim skalaren Kontext funktioniert, und wenn Sie $sizemehr als einmal verwenden möchten .

Ikegami
quelle
15
Persönlich bevorzuge ich die Version, die das Schlüsselwort "scalar" verwendet, da es ziemlich explizit ist, dass es einen skalaren Kontext erzwingt. my $size=@arrayEs scheint ein Fehler zu sein, bei dem das falsche Siegel verwendet wurde.
Nate CK
5
Das ist eine wirklich schlechte Idee. Menschen, die scalarohne Grund verwenden, lernen die falsche Lektion. Sie beginnen zu verstehen, dass Operatoren Listen zurückgeben, die zu Skalaren gezwungen werden können. Dutzende Male gesehen.
Ikegami
2
Warum ist das "kein Grund"? Sie verwenden, scalarweil Sie die Liste in einen skalaren Kontext zwingen. Das ist der richtige Grund, es zu benutzen. Ihr Beispiel macht genau das Gleiche, hängt jedoch davon ab, was Perl tut, wenn Sie eine Listenvariable in einem implizit skalaren Kontext auswerten. In Ihrem Beispiel muss der Leser daher über das implizite Verhalten von Perl in diesem Kontext Bescheid wissen. Sie fügen dem Ausdruck nur eine weitere Ebene impliziten Verhaltens hinzu, und Perl hat bereits zu viel implizites Verhalten, das Sie durchdenken müssen, um ein Programm zu entschlüsseln.
Nate CK
2
@Nate CK, Re "Warum ist das" kein Grund "? Sie verwenden, scalarweil Sie die Liste in einen skalaren Kontext zwingen". Sie haben meinen Standpunkt unter Beweis gestellt, die falsche Lektion zu lernen. Das ist völlig falsch. Keine Liste wird jemals von gezwungen scalar. (Wenn ja, scalar(@array)und scalar(@array[0..$#array])würde die gleiche Sache zurückzukehren.) scalar(@array)Erzählt @arrayeinen skalar zurückzukehren, mit dem Sie ihm schon gesagt , mit dem zu tun my $size=.
Ikegami
2
Ob Sie es glauben oder nicht, Entwickler müssen Code debuggen, der von anderen Entwicklern geschrieben wurde. Und Entwickler müssen Code debuggen, den sie vor drei Jahren geschrieben haben.
Nate CK
27

Dadurch wird die Größe ermittelt, indem das Array in einen skalaren Kontext gezwungen wird, in dem es als seine Größe ausgewertet wird:

print scalar @arr;

Dies ist eine weitere Möglichkeit, das Array in einen skalaren Kontext zu zwingen, da es einer skalaren Variablen zugewiesen wird:

my $arrSize = @arr;

Dadurch wird der Index des letzten Elements im Array abgerufen, also tatsächlich die Größe minus 1 (vorausgesetzt, die Indizes beginnen bei 0, was in Perl einstellbar ist, obwohl dies normalerweise eine schlechte Idee ist):

print $#arr;

Letzteres ist nicht wirklich gut, um die Array-Größe zu ermitteln. Es wäre nützlich, wenn Sie nur das letzte Element des Arrays erhalten möchten:

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

Wie Sie hier bei Stack Overflow sehen können, wird dieses Konstrukt von den meisten Syntax-Textmarkern nicht korrekt behandelt ...

Nate CK
quelle
2
Eine Nebenbemerkung: Verwenden Sie einfach $arr[-1], um das letzte Element zu erhalten. Und $arr[-2]um den vorletzten zu bekommen und so weiter.
Tuomassalo
1
@ Tuomassalo: Ich stimme zu, dass Ihr Vorschlag ein besserer Ansatz ist. Rückblickend $#arrist dies keine sehr nützliche Funktion, und es ist kein Zufall, dass andere Sprachen sie nicht haben.
Nate CK
6

Um den zweiten Weg zu verwenden, fügen Sie 1 hinzu:

print $#arr + 1; # Second way to print array size
jhoanna
quelle
for [0..$#array] { print $array[$_ ] } funktioniert jedoch sehr gut, wenn der Zweck des Abrufs der Anzahl der Elemente darin besteht, das Array zu durchlaufen. Der Vorteil ist, dass Sie das Element sowie einen Zähler erhalten, die ausgerichtet sind.
Westrock
5

Alle drei ergeben das gleiche Ergebnis, wenn wir das zweite etwas ändern:

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;
Zon
quelle
5
Unterscheidet sich das von dem, was bereits in dieser und dieser Antwort erwähnt wurde ?
devnull
5

Beispiel:

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

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

Der Abschnitt „Perl-Variablentypen“ in der Perlintro-Dokumentation enthält

Die spezielle Variable $#arraygibt den Index des letzten Elements eines Arrays an:

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

Sie könnten versucht sein $#array + 1, Ihnen mitzuteilen, wie viele Elemente sich in einem Array befinden. Mach dir keine Sorgen. Wenn Sie verwenden, @arraywo Perl erwartet, einen Skalarwert zu finden ("im Skalarkontext"), erhalten Sie die Anzahl der Elemente im Array:

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

Die Perldata-Dokumentation behandelt dies auch im Abschnitt „Skalarwerte“ .

Wenn Sie ein Array im skalaren Kontext auswerten, wird die Länge des Arrays zurückgegeben. (Beachten Sie, dass dies nicht für Listen gilt, die den letzten Wert zurückgeben, wie der C-Komma-Operator, oder für integrierte Funktionen, die alles zurückgeben, was sie zurückgeben möchten.) Folgendes gilt immer:

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

Einige Programmierer verwenden eine explizite Konvertierung, um keinen Zweifel zu lassen:

$element_count = scalar(@whatever);

Weiter oben im selben Abschnitt wird dokumentiert, wie der Index des letzten Elements eines Arrays ermittelt wird.

Die Länge eines Arrays ist ein Skalarwert. Sie können die Länge des Arrays @daysdurch Auswerten $#dayswie in ermitteln csh. Dies ist jedoch nicht die Länge des Arrays. Es ist der Index des letzten Elements, bei dem es sich um einen anderen Wert handelt, da normalerweise ein 0. Element vorhanden ist.

Greg Bacon
quelle
2

Es gibt verschiedene Möglichkeiten, die Größe des Arrays zu drucken. Hier sind die Bedeutungen von allem: Nehmen wir an, unser Array istmy @arr = (3,4);

Methode 1: Skalar

Dies ist der richtige Weg, um die Größe von Arrays zu ermitteln.

print scalar @arr;  # prints size, here 2

Methode 2: Indexnummer

$#arrgibt den letzten Index eines Arrays an. Wenn das Array also die Größe 10 hat, ist sein letzter Index 9.

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

Wir fügen hier 1 hinzu, wobei das Array als 0-indiziert betrachtet wird . Wenn es jedoch nicht auf Null basiert, schlägt diese Logik fehl .

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

Das obige Beispiel gibt 6 aus, da wir den Anfangsindex auf 4 gesetzt haben. Jetzt wäre der Index 5 und 6 mit den Elementen 3 bzw. 4.

Methode 3:

Wenn ein Array im skalaren Kontext verwendet wird, gibt es die Größe des Arrays zurück

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

Tatsächlich sind Methode 3 und Methode 1 gleich.

Kamal Nayan
quelle
2

Aus perldoc perldata , die sicher zu zitieren sein sollten:

Folgendes ist immer wahr:

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

Nur solange Sie nicht $ # was auch immer ++ und auf mysteriöse Weise die Größe oder Ihr Array erhöhen.

Die Array-Indizes beginnen mit 0.

und

Sie können ein Array auf nichts reduzieren, indem Sie ihm die Nullliste () zuweisen. Folgendes ist äquivalent:

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

Was mich zu dem bringt, wonach ich gesucht habe, ist, wie man erkennt, dass das Array leer ist. Ich habe es gefunden, wenn $ # leer == -1;

jwal
quelle
1

Was ist, int(@array)wenn es das Argument als Skalar bedroht ?

Reflektierend
quelle
0

Um die Größe eines Arrays zu ermitteln, verwenden Sie das scalarSchlüsselwort:

print scalar @array;

Um den letzten Index eines Arrays herauszufinden, gibt es $#(Perl-Standardvariable). Es gibt den letzten Index eines Arrays an. Wenn ein Array bei 0 beginnt, erhalten wir die Größe des Arrays, indem wir eins hinzufügen zu $#:

print "$#array+1";

Beispiel:

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

Ausgabe:

3

3
Sandeep_black
quelle