Manakah implementasi terbaik (dalam hal kecepatan dan penggunaan memori) untuk iterasi melalui larik Perl? Apakah ada cara yang lebih baik? ( @Array
tidak perlu disimpan).
Implementasi 1
foreach (@Array)
{
SubRoutine($_);
}
Implementasi 2
while($Element=shift(@Array))
{
SubRoutine($Element);
}
Implementasi 3
while(scalar(@Array) !=0)
{
$Element=shift(@Array);
SubRoutine($Element);
}
Implementasi 4
for my $i (0 .. $#Array)
{
SubRoutine($Array[$i]);
}
Implementasi 5
map { SubRoutine($_) } @Array ;
map
dan jawaban yang dapat diterima ?. dll.)Jawaban:
Dalam hal kecepatan: # 1 dan # 4, tetapi tidak banyak dalam banyak kasus.
Anda dapat menulis patokan untuk mengonfirmasi, tetapi saya curiga Anda akan menemukan # 1 dan # 4 menjadi sedikit lebih cepat karena pekerjaan iterasi dilakukan di C, bukan di Perl, dan tidak ada penyalinan elemen array yang tidak perlu terjadi. (
$_
adalah alias elemen di # 1, tetapi # 2 dan # 3 sebenarnya menyalin skalar dari array.)# 5 mungkin serupa.
Dalam hal penggunaan memori: Semuanya sama kecuali # 5.
for (@a)
dilapisi khusus untuk menghindari perataan array. Perulangan melakukan iterasi pada indeks array.Dalam hal keterbacaan: # 1.
Dalam hal fleksibilitas: # 1 / # 4 dan # 5.
# 2 tidak mendukung elemen yang salah. # 2 dan # 3 bersifat merusak.
sumber
my @todo = $root; while (@todo) { my $node = shift; ...; push @todo, ...; ...; }
Jika Anda hanya peduli tentang elemen
@Array
, gunakan:atau
Jika indeks penting, gunakan:
Atau, pada
perl
5.12.1, Anda dapat menggunakan:Jika Anda membutuhkan elemen dan indeksnya di badan loop,
Saya harapkanmenggunakaneach
menjadi yang tercepat, tapi kemudianAnda akan melepaskan kompatibilitas dengan pra-5.12.1perl
s.Beberapa pola lain selain ini mungkin sesuai dalam keadaan tertentu.
sumber
each
menjadi yang paling lambat. Itu melakukan semua pekerjaan yang lain tanpa alias, ditambah tugas daftar, dua salinan skalar dan dua pembersihan skalar.for
iterasi pada indeks array, dan 20% lebih cepat saat melakukan iterasi pada indeks referensi array (saya melakukan akses$array->[$i]
di dalam body), dibandingkan menggunakaneach
dalam hubungannya denganwhile
.IMO, implementasi # 1 adalah tipikal dan pendek dan idiomatis karena Perl mengalahkan yang lain untuk itu saja. Tolok ukur dari tiga pilihan mungkin menawarkan Anda wawasan tentang kecepatan, setidaknya.
sumber
1 secara substansial berbeda dari 2 dan 3, karena meninggalkan array dengan bijaksana, sedangkan dua lainnya membiarkannya kosong.
Saya akan mengatakan # 3 cukup aneh dan mungkin kurang efisien, jadi lupakan itu.
Yang membuat Anda mendapat # 1 dan # 2, dan mereka tidak melakukan hal yang sama, jadi yang satu tidak bisa "lebih baik" dari yang lain. Jika arraynya besar dan Anda tidak perlu menyimpannya, umumnya scope akan menghadapinya ( tapi lihat CATATAN ), jadi secara umum , # 1 masih merupakan metode yang paling jelas dan paling sederhana. Mematikan setiap elemen tidak akan mempercepat apa pun. Bahkan jika ada kebutuhan untuk membebaskan array dari referensi, saya hanya akan pergi:
ketika selesai.
sumber
@Array = ();
tidak membebaskan array yang mendasarinya. Bahkan tidak keluar dari ruang lingkup akan melakukan itu. Jika Anda ingin membebaskan array yang mendasarinya, Anda harus menggunakanundef @Array;
.perl -MDevel::Peek -e'my @a; Dump(\@a,1); @a=qw( a b c ); Dump(\@a,1); @a=(); Dump(\@a,1); undef @a; Dump(\@a,1);' 2>&1 | grep ARRAY
()
vsundef
, tetapi jika keluar dari ruang lingkup tidak melepaskan memori yang digunakan oleh array lokal ke ruang lingkup itu, bukankah itu membuat perl bencana bocor? Itu tidak benar.Dalam satu baris untuk mencetak elemen atau larik.
cetak $ _ untuk (@array);
CATATAN: ingat bahwa $ _ secara internal merujuk ke elemen @array dalam perulangan. Setiap perubahan yang dibuat di $ _ akan terlihat di @array; ex.
keluaran: 2 4 6
sumber
Cara terbaik untuk memutuskan pertanyaan seperti ini untuk membandingkannya:
Dan menjalankan ini pada perl 5, versi 24, subversi 1 (v5.24.1) dibangun untuk x86_64-linux-gnu-thread-multi
Saya mendapat:
Jadi 'foreach (@Array)' kira-kira dua kali lebih cepat dari yang lain. Semua yang lain sangat mirip.
@ikegami juga menunjukkan bahwa ada beberapa perbedaan dalam implimentasi ini selain kecepatan.
sumber
$index < $#array
sebenarnya harus$index <= $#array
karena$#array
bukan panjang array tetapi indeks terakhirnya.