Temukan ukuran array di Perl

243

Saya tampaknya telah menemukan beberapa cara berbeda untuk menemukan ukuran array. Apa perbedaan antara ketiga metode ini?

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
sumber
13
cara lain: print 0+@arr, print "".@arr,print ~~@arr
mob
3
@mob, hum, orang mungkin ingin menghindari "".@arrseperti "@arr"halnya sesuatu yang sangat berbeda.
ikegami
39
"Cara kedua" BUKAN cara untuk mencetak ukuran array ...
tadmc
dalam konteks skalar; @arr mengembalikan ukuran tabel. $ x = @ arr adalah konteks skalar. $ # arr mengembalikan indeks array terakhir. pengindeksan dimulai dari 0, maka benar persamaan $ # arr + 1 == @arr. Jika Anda menulis beberapa elemen di luar urutan, misalnya $ arr [100] = 'any', maka tabel secara otomatis ditingkatkan ke indeks maks 100, dan (termasuk indeks 0) menjadi 101 elemen.
Znik

Jawaban:

234

Cara pertama dan ketiga adalah sama: mereka mengevaluasi sebuah array dalam konteks skalar. Saya akan menganggap ini sebagai cara standar untuk mendapatkan ukuran array.

Cara kedua sebenarnya mengembalikan indeks terakhir dari array, yang tidak (biasanya) sama dengan ukuran array.

Chris Jester-Young
sumber
29
Ukuran (1,2,3) adalah 3, dan indeksnya (secara default) 0, 1 dan 2. Jadi, $ # arr akan menjadi 2 dalam kasus ini, bukan 3.
Nate CK
5
Variabel yang $[ditentukan menentukan "Indeks elemen pertama dalam array, dan karakter pertama dalam substring" ( perldoc perlvar). Ini diatur ke 0 secara default, dan pengaturan ke apa pun selain 0 sangat tidak dianjurkan.
Keith Thompson
5
@Keith Thompson, $[berkecil hati (dan telah selama satu dekade). $[sudah ditinggalkan. Menggunakan $[masalah peringatan penghentian bahkan ketika seseorang tidak menyalakan peringatan. Menetapkan apa pun kecuali nol untuk $[akan menjadi kesalahan dalam 5.16. Bisakah kita berhenti menyebutkan $[?
ikegami
2
@Keith Thompson, lebih tua dari 5.14, sebenarnya. Tapi seperti yang saya katakan, itu telah berkecil hati dan usang jauh lebih lama dari itu, dan seseorang yang menggunakan $[akan tahu efeknya.
ikegami
7
@ikegami: Ya, tapi seseorang berusaha memahami perbedaan antara scalar @arrdan masih$#arr harus memahami efek yang mungkin terjadi , meskipun jarang. $[
Keith Thompson
41

Pertama, yang kedua tidak setara dengan dua lainnya. $#arraymengembalikan indeks terakhir array, yang lebih kecil dari ukuran array.

Dua lainnya hampir sama. Anda hanya menggunakan dua cara berbeda untuk membuat konteks skalar. Itu datang ke pertanyaan keterbacaan.

Saya pribadi lebih suka yang berikut ini:

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

Saya merasa lebih jelas daripada

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

dan

my $size = @array;
say $size;

Yang terakhir terlihat cukup jelas sendirian seperti ini, tetapi saya menemukan bahwa garis tambahan menghilangkan kejelasan ketika bagian dari kode lain. Ini berguna untuk mengajarkan apa yang @arraydilakukan dalam konteks skalar, dan mungkin jika Anda ingin menggunakan $sizelebih dari sekali.

ikegami
sumber
15
Secara pribadi saya lebih suka versi yang menggunakan kata kunci "skalar", karena cukup eksplisit bahwa itu memaksa konteks skalar. my $size=@arraySepertinya itu mungkin kesalahan di mana sigil yang salah digunakan.
Nate CK
5
Itu ide yang sangat buruk. Orang yang menggunakan scalartanpa alasan mempelajari pelajaran yang salah. Mereka mulai masuk ke dalam kepala mereka bahwa operator mengembalikan daftar yang dapat dipaksa menjadi skalar. Terlihat puluhan kali.
ikegami
2
Mengapa ini "tanpa alasan"? Anda menggunakan scalarkarena Anda memaksa daftar untuk konteks skalar. Itulah alasan yang tepat untuk menggunakannya. Contoh Anda melakukan hal yang persis sama, tetapi bergantung pada apa yang dilakukan Perl ketika Anda mengevaluasi variabel daftar dalam konteks skalar yang tersirat. Dengan demikian, contoh Anda mengharuskan pembaca untuk mengetahui tentang perilaku implisit Perl dalam konteks itu. Anda hanya menambahkan satu lapisan perilaku implisit ke ekspresi, dan Perl sudah memiliki terlalu banyak perilaku implisit yang harus Anda pertimbangkan untuk menguraikan suatu program.
Nate CK
2
@Nate CK, Re "Mengapa ini" tanpa alasan "? Anda menggunakan scalarkarena Anda memaksa daftar untuk konteks skalar", Anda telah membuktikan poin saya tentang mempelajari pelajaran yang salah. Ini sepenuhnya salah. Tidak ada daftar yang dipaksa oleh scalar. (Jika ya, scalar(@array)dan scalar(@array[0..$#array])akan mengembalikan hal yang sama.) scalar(@array)Memberitahu @arrayuntuk mengembalikan skalar, yang sudah Anda suruh lakukan my $size=.
ikegami
2
Percaya atau tidak, pengembang harus men-debug kode yang ditulis oleh pengembang lain. Dan pengembang harus men-debug kode yang mereka tulis tiga tahun lalu.
Nate CK
27

Ini mendapatkan ukuran dengan memaksa array ke dalam konteks skalar, di mana ia dievaluasi sebagai ukurannya:

print scalar @arr;

Ini adalah cara lain untuk memaksa array ke dalam konteks skalar, karena ia ditugaskan ke variabel skalar:

my $arrSize = @arr;

Ini mendapatkan indeks dari elemen terakhir dalam array, jadi sebenarnya ukuran minus 1 (dengan asumsi indeks mulai dari 0, yang dapat disesuaikan di Perl meskipun hal itu biasanya merupakan ide yang buruk):

print $#arr;

Yang terakhir ini tidak terlalu bagus untuk digunakan untuk mendapatkan ukuran array. Akan bermanfaat jika Anda hanya ingin mendapatkan elemen terakhir dari array:

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

Juga, seperti yang Anda lihat di sini di Stack Overflow, konstruk ini tidak ditangani dengan benar oleh kebanyakan sintaksis ...

Nate CK
sumber
2
A sidenote: cukup gunakan $arr[-1]untuk mendapatkan elemen terakhir. Dan $arr[-2]untuk mendapatkan yang kedua dari belakang, dan seterusnya.
tuomassalo
1
@tuomassalo: Saya setuju bahwa saran Anda adalah pendekatan yang lebih baik. Dalam retrospeksi, $#arrbukan fitur yang sangat berguna, dan bukan kebetulan bahwa bahasa lain tidak memilikinya.
Nate CK
6

Untuk menggunakan cara kedua, tambahkan 1:

print $#arr + 1; # Second way to print array size
jhoanna
sumber
for [0..$#array] { print $array[$_ ] } bekerja dengan sangat baik meskipun jika tujuan mendapatkan jumlah elemen adalah untuk beralih melalui array. Keuntungannya adalah Anda mendapatkan elemen serta penghitung yang selaras.
Westrock
5

Ketiganya memberikan hasil yang sama jika kita sedikit memodifikasi yang kedua:

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
sumber
5
Apakah hal ini berbeda dari apa yang telah disebutkan dalam ini jawaban dan ini salah satu?
devnull
5

Contoh:

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

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

Bagian “Perl variable types” dari dokumentasi perlintro berisi

Variabel khusus $#arraymemberi tahu Anda indeks elemen terakhir array:

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

Anda mungkin tergoda untuk menggunakannya $#array + 1untuk memberi tahu Anda berapa banyak item yang ada dalam array. Jangan repot-repot. Seperti yang terjadi, menggunakan di @arraymana Perl mengharapkan untuk menemukan nilai skalar ("dalam konteks skalar") akan memberi Anda jumlah elemen dalam array:

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

The dokumentasi perldata juga mencakup ini dalam “nilai-nilai skalar” bagian .

Jika Anda mengevaluasi array dalam konteks skalar, ia mengembalikan panjang array. (Perhatikan bahwa ini tidak benar dari daftar, yang mengembalikan nilai terakhir, seperti operator koma C, atau fungsi bawaan, yang mengembalikan apa pun yang mereka inginkan). Berikut ini selalu benar:

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

Beberapa programmer memilih untuk menggunakan konversi eksplisit sehingga tidak ada keraguan:

$element_count = scalar(@whatever);

Sebelumnya di bagian yang sama mendokumentasikan cara mendapatkan indeks elemen terakhir array.

Panjang array adalah nilai skalar. Anda dapat menemukan panjang array @daysdengan mengevaluasi $#days, seperti pada csh. Namun, ini bukan panjang array; itu adalah subskrip dari elemen terakhir, yang merupakan nilai yang berbeda karena biasanya ada elemen ke-0.

Greg Bacon
sumber
2

Ada berbagai cara untuk mencetak ukuran array. Inilah arti dari semuanya: Katakanlah array kita adalahmy @arr = (3,4);

Metode 1: skalar

Ini adalah cara yang tepat untuk mendapatkan ukuran array.

print scalar @arr;  # prints size, here 2

Metode 2: Nomor indeks

$#arrmemberikan indeks terakhir dari sebuah array. jadi jika array berukuran 10 maka indeks terakhirnya adalah 9.

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

Kami menambahkan 1 di sini mengingat array sebagai 0-diindeks . Tapi, jika bukan nol maka logika ini akan gagal .

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

Contoh di atas mencetak 6, karena kami telah menetapkan indeks awal menjadi 4. Sekarang indeks akan menjadi 5 dan 6, dengan masing-masing elemen 3 dan 4.

Metode 3:

Ketika sebuah array digunakan dalam konteks skalar, maka ia mengembalikan ukuran array

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

Sebenarnya metode 3 dan metode 1 sama.

Kamal Nayan
sumber
2

Dari perldoc perldata , yang seharusnya aman untuk dikutip:

Berikut ini selalu benar:

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

Asalkan Anda tidak $ # apa pun ++ dan secara misterius meningkatkan ukuran atau array Anda.

Indeks array dimulai dengan 0.

dan

Anda dapat memangkas array menjadi kosong dengan menetapkan daftar nol () padanya. Berikut ini adalah setara:

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

Yang membawa saya ke apa yang saya cari yaitu cara mendeteksi array kosong. Saya menemukannya jika $ # kosong == -1;

jwal
sumber
1

Bagaimana int(@array)dengan itu mengancam argumen sebagai skalar.

Reflektif
sumber
0

Untuk menemukan ukuran array gunakan scalarkata kunci:

print scalar @array;

Untuk mengetahui indeks terakhir dari array ada $#(Perl default variabel). Ini memberikan indeks terakhir dari sebuah array. Ketika sebuah array dimulai dari 0, kita mendapatkan ukuran array dengan menambahkan satu ke $#:

print "$#array+1";

Contoh:

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

Keluaran:

3

3
Sandeep_black
sumber