Perl'de bir dizinin boyutunu bulma


243

Bir dizinin boyutunu bulmak için birkaç farklı yolla rastladım. Bu üç yöntem arasındaki fark nedir?

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
başka yolları: print 0+@arr, print "".@arr,print ~~@arr
mafya

3
@mob, hum, tek kaçınmak isteyebilirsiniz "".@arrolarak "@arr"oldukça farklı bir şey yapar.
ikegami

39
"İkinci yol" dizi boyutu yazdırmak için bir yol değildir ...
tadmc

skaler bağlamda; @arr tablo boyutunu döndürür. $ x = @ arr skaler bağlamdır. $ # arr dizinin son dizinini döndürür. indeksleme 0'dan başlayarak doğru denklem $ # arr + 1 == @arr olur. Bazı öğeleri bozuk yazarsanız, örneğin $ arr [100] = 'any', tablo otomatik olarak maks. Dizin 100'e ve (dizin 0 dahil) 101 elemente yükseltilir.
Znik

Yanıtlar:


234

Birinci ve üçüncü yollar aynıdır: bir diziyi skaler bağlamda değerlendirirler. Bu bir dizi boyutu almak için standart bir yol olarak düşünürdüm.

İkinci yol aslında dizinin (genellikle) dizi boyutuyla aynı olmayan son dizini döndürür.


29
(1,2,3) boyutu 3'tür ve dizinler (varsayılan olarak) 0, 1 ve 2'dir. Bu nedenle, bu durumda $ # arr 2 olur, 3 değil.
Nate CK

5
Öntanımlı değişken $["Bir dizideki ilk öğenin ve bir alt dizideki ilk karakterin dizini" ( perldoc perlvar) öğesini belirtir . Varsayılan olarak 0 olarak ayarlanmıştır ve 0 dışında bir değere ayarlanması önerilmez.
Keith Thompson

5
@Teith Thompson, $[cesareti kırıldı (ve on yıldır var). $[kullanımdan kaldırıldı. $[Uyarılar açılmasa bile kullanımdan kaldırma uyarısı kullanmak . Sıfır dışında bir şey atamak 5.16'da $[bir hata olacaktır. $[Zaten bahsetmeyi bırakabilir miyiz ?
ikegami

2
@Teith Thompson, aslında 5.14'ten daha yaşlı. Ama dediğim gibi, bundan daha uzun bir süre için cesareti kırıldı ve kullanımdan kaldırıldı ve kullanan biri $[etkilerini bilecekti.
ikegami

7
@ikegami: Evet, ama biri arasındaki farkı anlamaya çalışan scalar @arrve $#arrgerektiği hala olası etkilerini anlamak $[olsalar nadir.
Keith Thompson

41

Birincisi, ikincisi diğer ikisine eşdeğer değildir. $#arraydizinin boyutundan bir küçük olan dizinin son dizinini döndürür.

Diğer ikisi neredeyse aynı. Skaler bağlam oluşturmak için iki farklı yol kullanıyorsunuz. Okunabilirlik meselesi geliyor.

Şahsen aşağıdakileri tercih ederim:

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

Daha net buluyorum

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

ve

my $size = @array;
say $size;

İkincisi bu şekilde tek başına oldukça net görünüyor, ancak ekstra satırın diğer kodun bir parçası olduğunda netlikten uzaklaştığını görüyorum. @arraySkaler bağlamda neler yaptığını öğretmek için faydalıdır ve belki de $sizebirden fazla kullanmak istiyorsanız .


15
Şahsen "skaler" anahtar kelimesini kullanan sürümü tercih ediyorum, çünkü skaler bir bağlamı zorladığı oldukça açık. my $size=@arrayyanlış sigil'in kullanıldığı bir hata olabilir.
Nate CK

5
Bu gerçekten kötü bir fikir. scalarSebepsiz kullanan insanlar yanlış dersi öğrenirler. Operatörlerin skalerlere zorlanabilecek listeleri döndürdükleri kafalarına girmeye başlarlar. Düzinelerce kez gördüm.
ikegami

2
Neden bu "sebep yok"? scalarListeyi skaler bir bağlama zorlamakta olduğunuz için kullanıyorsunuz . Bunu kullanmak için doğru sebep budur. Örneğiniz aynı şeyi yapar, ancak bir liste değişkenini örtük olarak skaler bağlamda değerlendirdiğinizde Perl'in ne yaptığına dayanır. Bu nedenle, örneğin, okuyucunun Perl'in bu bağlamdaki örtülü davranışını bilmesini gerektirir. İfadeye yalnızca bir örtülü davranış katmanı daha ekliyorsunuz ve Perl zaten bir programı deşifre etmek için aklınızda bulundurmanız gereken çok fazla örtük davranışa sahip.
Nate CK

2
@Nate CK, Re "Neden bu" sebep yok? scalar" Bu tamamen yanlış. Hiçbir liste tarafından zorlanmaz scalar. (Öyle ise scalar(@array)ve scalar(@array[0..$#array])aynı şeyi döndürürse.) Bunu zaten söylemiş olduğunuz bir skaleri iade etmeyi scalar(@array)söyler . @arraymy $size=
ikegami

2
İster inanın ister inanmayın, geliştiriciler diğer geliştiriciler tarafından yazılan kodda hata ayıklamak zorundadır. Ve geliştiriciler üç yıl önce yazdıkları kodda hata ayıklamak zorundalar.
Nate CK

27

Bu, diziyi boyut olarak değerlendirildiği skaler bir bağlama zorlayarak boyutu alır:

print scalar @arr;

Bu, diziyi skaler bir değişkene atandığı için diziyi skaler bir bağlama zorlamanın başka bir yoludur:

my $arrSize = @arr;

Bu, dizideki son öğenin dizinini alır, bu nedenle aslında eksi 1 boyutudur (dizinlerin 0'da başladığını varsayarsak, bunu yapmak genellikle kötü bir fikir olsa da Perl'de ayarlanabilir):

print $#arr;

Bu sonuncusu dizi boyutunu elde etmek için kullanmak gerçekten iyi değil. Dizinin son öğesini almak istiyorsanız yararlı olacaktır:

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

Ayrıca, burada Stack Overflow'da da görebileceğiniz gibi, bu yapı sözdizimi vurgulayıcılarının çoğu tarafından doğru şekilde ele alınmamaktadır ...


2
Bir sidenote: sadece $arr[-1]son elemanı almak için kullanın . Ve $arr[-2]sondan bir tanesini almak için, vb.
tuomassalo

1
@tuomassalo: Önerinizin daha iyi bir yaklaşım olduğunu kabul ediyorum. Geriye dönüp bakıldığında, $#arrçok kullanışlı bir özellik değildir ve diğer dillerin buna sahip olması tesadüf değildir.
Nate CK

6

İkinci yolu kullanmak için 1 ekleyin:

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

for [0..$#array] { print $array[$_ ] } öğelerin sayısını alma amacı dizi üzerinden yineleme yapmak ise gerçekten iyi çalışır. Avantajı, öğeyi ve hizalanmış bir sayacı almanızdır.
Westrock

5

İkincisini biraz değiştirirsek her üçü de aynı sonucu verir:

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
Bu, bu cevapta ve bu cevapta daha önce bahsedilenlerden farklı bir şey mi?
devnull

5

Misal:

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

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

2

“Perl değişken türleri” bölümüne ait perlintro belgelerine içerir

Özel değişken $#arraysize bir dizinin son elemanının dizinini söyler:

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

$#array + 1Bir dizide kaç öğe olduğunu size bildirmek için cazip olabilirsiniz . Rahatsız etme. Olduğu gibi, @arrayPerl'in bir skaler değer bulmayı beklediği yeri kullanmak (“skaler bağlamda”) dizideki öğe sayısını verecektir:

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

Perldata belgeler de bu kapakları “Skaler değerler” bölümünde .

Bir diziyi skaler bağlamda değerlendirirseniz, dizinin uzunluğunu döndürür. (Bunun, C virgül operatörü gibi son değeri döndüren listeler veya geri dönmek istediklerini döndüren yerleşik işlevler için geçerli olmadığını unutmayın.) Aşağıdakiler her zaman doğrudur:

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

Bazı programcılar şüphesiz hiçbir şey bırakmamak için açık bir dönüşüm kullanmayı tercih eder:

$element_count = scalar(@whatever);

Aynı bölümün başlarında, bir dizinin son öğesinin dizininin nasıl elde edileceğini belgeler.

Bir dizinin uzunluğu skaler bir değerdir. Dizinin uzunluğunu , olduğu gibi @daysdeğerlendirerek bulabilirsiniz . Ancak, bu dizinin uzunluğu değildir; normalde 0'cı eleman olduğundan farklı bir değer olan son elemanın aboneliğidir.$#dayscsh


2

Dizi boyutunu yazdırmanın çeşitli yolları vardır. İşte hepsinin anlamları: Diyelim ki dizimizmy @arr = (3,4);

Yöntem 1: Skaler

Dizilerin boyutunu elde etmenin doğru yolu budur.

print scalar @arr;  # prints size, here 2

Yöntem 2: Dizin numarası

$#arrdizinin son dizinini verir. yani dizi 10 büyüklüğündeyse, son dizini 9 olur.

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

Diziyi 0 dizinli olarak kabul ederek 1 ekliyoruz . Ancak, sıfır tabanlı değilse, bu mantık başarısız olacaktır .

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

Yukarıdaki örnek 6'yı yazdırır, çünkü başlangıç ​​dizinini 4 olarak ayarladık. Şimdi dizin sırasıyla 3 ve 4 ile 5 ve 6 olacaktır.

Yöntem 3:

Bir dizi skaler bağlamda kullanıldığında, dizinin boyutunu döndürür

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

Aslında yöntem 3 ve yöntem 1 aynıdır.


2

Perldoc itibaren perldata alıntı güvenli olmalı,:

Aşağıdakiler her zaman doğrudur:

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

Sadece $ # ne olursa olsun ++ $ ve gizemli bir şekilde boyutu veya dizi artırmak sürece.

Dizi indeksleri 0 ile başlar.

ve

Bir null listesini () atayarak bir diziyi hiçbir şey için kısaltabilirsiniz. Aşağıdakiler eşdeğerdir:

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

Bu da beni aradığım şeye götürüyor, bu da dizinin nasıl tespit edileceğinin boş olduğu. $ # Empty == -1;



0

Bir dizinin boyutunu bulmak için scalaranahtar kelimeyi kullanın :

print scalar @array;

Bir dizinin son dizinini bulmak için $#(Perl varsayılan değişkeni) vardır. Bir dizinin son dizinini verir. Bir dizi 0'dan başladığında, diziye bir tane ekleyerek dizinin boyutunu elde ederiz $#:

print "$#array+1";

Misal:

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

Çıktı:

3

3
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.