Memeriksa larik kosong: hitung vs kosong

98

Pertanyaan tentang ' Bagaimana cara mengetahui apakah array PHP kosong ' ini membuat saya memikirkan pertanyaan ini

Apakah ada alasan yang countharus digunakan daripada emptysaat menentukan apakah sebuah array kosong atau tidak?

Pemikiran pribadi saya adalah jika 2 setara untuk kasus larik kosong yang harus Anda gunakan emptykarena memberikan jawaban boolean untuk pertanyaan boolean. Dari pertanyaan yang ditautkan di atas, tampaknya itulah count($var) == 0metode yang populer. Bagi saya, meski secara teknis benar, tidak masuk akal. Misalnya Q: $ var, apakah Anda kosong? J: 7 . Hmmm...

Adakah alasan saya harus menggunakan count == 0sebagai gantinya atau hanya masalah selera pribadi?

Seperti yang ditunjukkan oleh orang lain dalam komentar untuk jawaban yang sekarang dihapus, countakan berdampak pada kinerja untuk array besar karena harus menghitung semua elemen, sedangkan emptydapat berhenti segera setelah mengetahui bahwa itu tidak kosong. Jadi, jika mereka memberikan hasil yang sama dalam kasus ini, tetapi countberpotensi tidak efisien, mengapa kami menggunakan count($var) == 0?

Dan McGrath
sumber
Saya berasumsi niat Anda adalah membatasi percakapan secara eksklusif ke array, tetapi mungkin perlu dicatat bahwa permainan berubah sepenuhnya jika Anda bekerja dengan objek (misalnya, yang menerapkan Countable, Iterator, dll.).
8
Array kosong sama dengan falsedi PHP - tidak perlu empty()atau count().
Cobby
@Cobby Code tolong.
TheRealChx101
@ TheRealChx101 Seperti, lakukan saja: if (!$myArray) { echo "array is empty"; } sandbox.onlinephpfunctions.com/code/…
Cobby
Saat ini, opsi populer dalam pertanyaan terkait adalah menggunakan empty().
PhoneixS

Jawaban:

97

Saya biasanya menggunakan empty. Saya tidak yakin mengapa orang benar-benar menggunakan hitungan - Jika array besar maka hitungan membutuhkan waktu lebih lama / memiliki lebih banyak overhead. Jika Anda hanya ingin mengetahui apakah array kosong atau tidak, gunakan kosong.

prodigitalson
sumber
4
Fungsi-fungsi ini memang berbeda jika lariknya tidak kosong.
Jacco
2
@ Jacco: Saya tidak mempermasalahkan itu. Tetapi jika Anda mengujinya kosong, saya tidak melihat relevansi apa yang dimilikinya - ini adalah pertanyaan dengan hasil boolean yang merupakan fungsi yang akan dikembalikan. Berkenaan dengan apa yang dianggap kosong di jangan melihat bagaimana kriteria tersebut akan menghasilkan jawaban yang salah kecuali var pengujian Anda bukan larik dalam hal itu merupakan masalah yang sama sekali berbeda.
ajaib
23
@prodigitalson Saya akan mengatakan hitungan itu O(1), karena PHP menyimpan jumlah elemen secara internal. Lihat jawaban ini stackoverflow.com/a/5835419/592454
elital
4
@eliton: tetapi tetap - bahkan jika tidak ada atau sedikit perbedaan dalam kinerja mengapa menggunakan hitungan jika Anda tidak perlu menghitung?
ajaib
4
kosong () terlalu memaafkan kesalahan. Saya baru saja menghabiskan 2 jam men-debug subclass yang menguji empty () pada variabel anggota pribadi dari superclass-nya (ruang lingkup variabel anggota superclass HARUS dilindungi, tetapi empty () tidak mengembalikan kesalahan - hasilnya hanyalah sesuatu yang seharusnya telah terjadi, tidak terjadi: tidak adanya variabel anggota dalam subkelas diperlakukan persis dengan cara yang sama seolah-olah variabel anggota ini, sebuah array, kosong - yaitu seolah-olah tidak memiliki elemen). Ini bermasalah, dan contoh lain PHP terlalu pemaaf.
Matthew Slyman
46

Saya penasaran ingin melihat mana yang sebenarnya lebih cepat jadi saya membuat skrip sederhana untuk mengukur fungsi tersebut.

<?php

function benchmark($name, $iterations, $action){
    $time=microtime(true);
    for($i=0;$i<=$iterations;++$i){
        $action();
    }
    echo $name . ' ' . round(microtime(true)-$time, 6) . "\n";
}

$iterations = 1000000;
$x = array();
$y = range(0, 10000000);
$actions = array(
    "Empty empty()" => function() use($x){
        empty($x);
    },
    "Empty count()" => function() use($x){
        count($x);
    },
    "Full empty()" => function() use($y){
        empty($y);
    },
    "Full count()" => function() use($y){
        count($y);
    },
    ############
    "IF empty empty()" => function() use($x){
        if(empty($x)){ $t=1; }
    },
    "IF empty count()" => function() use($x){
        if(count($x)){ $t=1; }
    },
    "IF full empty()" => function() use($y){
        if(empty($y)){ $t=1; }
    },
    "IF full count()" => function() use($y){
        if(count($y)){ $t=1; }
    },
    ############
    "OR empty empty()" => function() use($x){
        empty($x) OR $t=1;
    },
    "OR empty count()" => function() use($x){
        count($x) OR $t=1;
    },
    "OR full empty()" => function() use($y){
        empty($y) OR $t=1;
    },
    "OR full count()" => function() use($y){
        count($y) OR $t=1;
    },
    ############
    "IF/ELSE empty empty()" => function() use($x){
        if(empty($x)){ $t=1; } else { $t=2; }
    },
    "IF/ELSE empty count()" => function() use($x){
        if(count($x)){ $t=1; } else { $t=2; }
    },
    "IF/ELSE full empty()" => function() use($y){
        if(empty($y)){ $t=1; } else { $t=2; }
    },
    "IF/ELSE full count()" => function() use($y){
        if(count($y)){ $t=1; } else { $t=2; }
    },
    ############
    "( ? : ) empty empty()" => function() use($x){
        $t = (empty($x) ? 1 : 2);
    },
    "( ? : ) empty count()" => function() use($x){
        $t = (count($x) ? 1 : 2);
    },
    "( ? : ) full empty()" => function() use($y){
        $t = (empty($y) ? 1 : 2);
    },
    "( ? : ) full count()" => function() use($y){
        $t = (count($y) ? 1 : 2);
    }
);

foreach($actions as $name => $action){
    benchmark($name, $iterations, $action);
}
//END

Karena saya melakukannya, saya juga mencoba memeriksa kinerja melakukan operasi yang biasanya dikaitkan dengan count () / empty ()

Menggunakan PHP 5.4.39:

Empty empty() 0.118691
Empty count() 0.218974
Full empty() 0.133747
Full count() 0.216424
IF empty empty() 0.166474
IF empty count() 0.235922
IF full empty() 0.120642
IF full count() 0.248273
OR empty empty() 0.123875
OR empty count() 0.258665
OR full empty() 0.157839
OR full count() 0.224869
IF/ELSE empty empty() 0.167004
IF/ELSE empty count() 0.263351
IF/ELSE full empty() 0.145794
IF/ELSE full count() 0.248425
( ? : ) empty empty() 0.169487
( ? : ) empty count() 0.265701
( ? : ) full empty() 0.149847
( ? : ) full count() 0.252891

Menggunakan HipHop VM 3.6.1 (dbg)

Empty empty() 0.210652
Empty count() 0.212123
Full empty() 0.206016
Full count() 0.204722
IF empty empty() 0.227852
IF empty count() 0.219821
IF full empty() 0.220823
IF full count() 0.221397
OR empty empty() 0.218813
OR empty count() 0.220105
OR full empty() 0.229118
OR full count() 0.221787
IF/ELSE empty empty() 0.221499
IF/ELSE empty count() 0.221274
IF/ELSE full empty() 0.221879
IF/ELSE full count() 0.228737
( ? : ) empty empty() 0.224143
( ? : ) empty count() 0.222459
( ? : ) full empty() 0.221606
( ? : ) full count() 0.231288

Kesimpulan jika Anda menggunakan PHP:

  1. empty () jauh lebih cepat daripada count () di kedua skenario, dengan larik kosong dan terisi

  2. count () melakukan hal yang sama dengan array penuh atau kosong.

  3. Melakukan IF sederhana atau hanya operasi Boolean adalah sama.

  4. IF / ELSE sangat sedikit lebih efisien daripada (?:). Kecuali Anda melakukan miliaran iterasi dengan ekspresi di tengah, itu sama sekali tidak signifikan.

Kesimpulan jika Anda menggunakan HHVM:

  1. empty () adalah sedikit lebih cepat daripada count () tetapi tidak begitu signifikan.

    [Selebihnya sama seperti di PHP]

Sebagai kesimpulan, jika Anda hanya ingin mengetahui apakah array kosong selalu gunakan empty ();

Ini hanyalah tes aneh yang dilakukan tanpa memperhitungkan banyak hal. Ini hanyalah bukti konsep dan mungkin tidak mencerminkan operasi dalam produksi.

Satake
sumber
Terima kasih untuk kode pengujian sampel .... Saya baru saja menggunakannya dan menemukan bahwa if($x){lebih cepat daripada if(empty($x)){(hanya berfungsi jika Anda tahu yang $xtelah dinyatakan).
Redzarf
Kode tes Anda sangat buruk. Anda menambahkan banyak hal tambahan, seperti panggilan fungsi anonim. Jika saya menghapus dan saya hanya menjalankan kode telanjang (untuk siklus setelah satu sama lain) maka saya mendapatkan perbedaan besar. Dan maksud saya dalam hal itu lebih cepat jika tidak ada countdan emptypanggilan dalam pernyataan if. Kemudian datang emptydan terakhir count. Tetapi dibandingkan dengan milik Anda dalam kasus telanjang, yang kosong sepuluh kali lebih cepat! Uji larik sederhana: 0,104662, kosong: 0,177659, hitung: 1,175125 pada PHP 5.6 jika tidak kode Anda memberikan hasil yang sama pada versi ini juga seperti yang Anda sebutkan. Hanya saja itu hasil palsu.
golddragon007
16

Saya pikir itu hanya preferensi pribadi. Beberapa orang mungkin mengatakan emptylebih cepat (misalnya http://jamessocol.com/projects/count_vs_empty.php ) sementara yang lain mungkin mengatakan countlebih baik karena pada awalnya dibuat untuk array. emptylebih umum dan dapat diterapkan pada jenis lain.

php.net memberikan peringatan berikut untuk count:

count () dapat mengembalikan 0 untuk variabel yang tidak disetel, tetapi juga dapat mengembalikan 0 untuk variabel yang telah diinisialisasi dengan larik kosong. Gunakan isset () untuk menguji apakah variabel disetel.

Dengan kata lain, jika variabel tidak disetel, Anda akan mendapat pemberitahuan dari PHP yang mengatakan bahwa itu tidak ditentukan. Oleh karena itu, sebelum menggunakan count, sebaiknya periksa variabel dengan isset. Ini tidak perlu dengan empty.

Laurent le Beau-Martin
sumber
3
Sangat menarik bahwa argumen yang mendukung countadalah bahwa itu pada awalnya dibuat untuk array ... namun objek dapat diimplementasikan Countable, dan Anda dapat meneruskan nilai skalar ke count()dan mendapatkan hasil yang valid.
1
count () dapat kembali 0 untuk variabel yang tidak diatur, tetapi mungkin juga ... . Dokumentasi resmi menggunakan kata kerja modal untuk mengungkapkan ketidakpastiannya: p
nawfal
Hanya komentar tentang hal isset()itu. Jika Anda khawatir tentang pemberitahuan di PHP, Anda seharusnya sudah mendeklarasikan array Anda. Jika Anda membiarkan PHP secara dinamis mendeklarasikan array Anda, Anda akan mendapatkan pemberitahuan pada saat itu juga. Saya pikir poin sebenarnya dari peringatan di php.net adalah bahwa Anda tidak boleh menggunakan countuntuk menentukan apakah sebuah array telah dideklarasikan atau tidak karena itu menghasilkan hasil yang sama seperti array kosong.
Noah Duncan
12

Apakah ada alasan bahwa hitungan harus digunakan daripada kosong saat menentukan apakah sebuah array kosong atau tidak?

Ada, ketika Anda perlu melakukan sesuatu pada array yang tidak kosong dengan mengetahui ukurannya:

if( 0 < ( $cnt = count($array) ) )
{
 echo "Your array size is: $cnt";
}
else
 echo "Too bad, your array is empty :(";

Tetapi saya tidak akan merekomendasikan penggunaan hitungan, kecuali Anda 100% yakin, bahwa yang Anda hitung adalah sebuah array. Akhir-akhir ini saya telah men-debug kode, di mana fungsi kesalahan kembali FALSEdaripada array kosong, dan yang saya temukan adalah:

var_dump(count(FALSE));

keluaran:

int 1

Jadi sejak itu saya menggunakan emptyatau if(array() === $array)untuk memastikan bahwa saya memiliki array yang kosong.

dev-null-dweller
sumber
6

count()tampaknya bekerja lebih baik dengan antarmuka mirip larik yang diterapkan ArrayAccess/Countable. empty()mengembalikan nilai true untuk jenis objek ini meskipun tidak memiliki elemen. Biasanya kelas-kelas ini akan mengimplementasikan Countableantarmuka, jadi jika pertanyaannya adalah "Apakah koleksi ini berisi elemen?" tanpa membuat asumsi tentang implementasinya, maka itu count()adalah pilihan yang lebih baik.

Ryan
sumber
Apakah maksud Anda " emptymengembalikan nilai salah untuk jenis objek ini meskipun tidak memiliki elemen"?
alexw
Iya. Tidak ada antarmuka yang memungkinkan kelas untuk menentukan apakah itu "kosong" atau tidak. Dan tidak masuk akal jika ada satu.
Ryan
+1 Penggunaan countakan menjadi solusi yang lebih fleksibel dan dapat diperluas jika masuk akal bagi kode Anda untuk menerima koleksi yang menerapkan cara "umum" ... IMO yang mungkin menjadi satu-satunya kriteria yang relevan untuk menentukan jika Anda menggunakan countatau cara lain ...
ClemC
Kelemahan besar count()pada 7.2 adalah tidak dapat lagi mengambil variabel kosong.
Ryan
5

Alternatifnya, Anda dapat mentransmisikan variabel sebagai boolean (secara implisit atau eksplisit):

if( $value )
{
  // array is not empty
}

if( (bool) $value )
{
  // array is still not empty
}

Metode ini menghasilkan E_NOTICEjika variabel tidak ditentukan, mirip dengan count().

Untuk informasi lebih lanjut, lihat halaman Manual PHP tentang perbandingan tipe .


sumber
1
Ini adalah cara terbaik untuk memeriksa, hanya gunakan empty()jika Anda secara eksplisit mencoba untuk menghindari pemicuan E_NOTICE (yang umumnya merupakan ide yang buruk, IMO). Penggunaan kosong secara terang-terangan akan menyebabkan kode buggy.
Cobby
3

Preferensi pribadi saya lebih pada pengkodean keanggunan (dalam kaitannya dengan kasus penggunaan spesifik saya). Saya setuju dengan Dan McG karena count () tidak merespons dengan tipe data yang benar (dalam hal ini boolean) untuk pengujian yang dimaksud yang memaksa pengembang untuk menulis lebih banyak kode untuk mengisi pernyataan 'jika'.

Apakah ini berdampak signifikan pada kinerja hanya dapat diperdebatkan untuk array yang sangat besar (yang mungkin Anda tidak akan memiliki alokasi memori yang cukup untuk bagaimanapun juga di sebagian besar pengaturan).

Khususnya ketika datang ke array $ _POST PHP, tampaknya jauh lebih "logis" menurut saya untuk menulis / melihat:

if ( !empty ( $_POST ) ) {
    // deal with postdata
}
simonhamp
sumber
3

Semoga ini bisa membantu seseorang meskipun sudah dijawab (dan diperdebatkan beberapa apa). Dalam skenario saya sendiri, saya tahu semua array saya semua memiliki 7 elemen (pemeriksaan dilakukan sebelumnya dalam kode saya) dan saya melakukan array_diffyang tentu saja mengembalikan array nol ketika sama.

Saya memiliki 34 detik untuk countdan 17 detik untuk empty. Keduanya memberi saya perhitungan yang sama sehingga kode saya masih baik-baik saja.

Namun Anda juga dapat mencoba ==atau ===seperti di PHP - Periksa apakah dua array sama . Yang terbaik yang akan saya katakan adalah coba countvs emptyvs == empty array, lalu lihat mana yang memberikan kinerja terbaik Anda. Dalam kasus saya countadalah yang paling lambat jadi saya menggunakan emptysekarang ... akan memeriksa serializeberikutnya

xchiltonx.dll
sumber
2

Tidak ada alasan yang kuat untuk memilih count($myArray) == 0lebih empty($myArray). Mereka memiliki semantik yang identik. Beberapa mungkin menemukan satu lebih mudah dibaca daripada yang lain. Satu mungkin berkinerja sedikit lebih baik daripada yang lain tetapi itu tidak mungkin menjadi faktor signifikan dalam sebagian besar aplikasi php. Untuk semua tujuan praktis, pilihannya adalah soal selera.

Asaf
sumber
1
Bagaimana dengan hal "kinerja"? Menggunakan penjelasan tentang "tujuan praktis" mengarah pada kebiasaan buruk. Gunakan countsaat Anda perlu menghitung, gunakan emptysaat Anda perlu memeriksa apakah koleksi kosong. Tentu saja ada kasus tepi seperti string atau null, tetapi programmer perlu memikirkan kodenya. Anda mungkin tidak setuju, Anda diizinkan.
Namek
beberapa kali, dengan count ($ myArray) jika $ myArray adalah booleen seperti nilai FALSE, hitungannya tidak berfungsi (diuji pada php5.3).
Mimouni
1

Terkadang menggunakan kosong adalah suatu keharusan. Contoh kode ini:

$myarray = array();

echo "myarray:"; var_dump($myarray); echo "<br>";
echo "case1 count: ".count($myarray)."<br>";
echo "case1 empty: ".empty($myarray)."<br>";

$glob = glob('sdfsdfdsf.txt');

echo "glob:"; var_dump($glob); echo "<br>";
echo "case2 count: ".count($glob)."<br>";
echo "case2 empty: ".empty($glob);

Jika Anda menjalankan kode ini seperti ini: http://phpfiddle.org/main/code/g9x-uwi

Anda mendapatkan keluaran ini:

myarray:array(0) { } 
case1 count: 0
case1 empty: 1

glob:bool(false) 
case2 count: 1
case2 empty: 1

Jadi jika Anda countkeluaran glob kosong, Anda mendapatkan keluaran yang salah. Anda harus memeriksa kekosongan.

Dari dokumentasi glob :

Mengembalikan larik yang berisi file / direktori yang cocok, larik kosong jika tidak ada file yang cocok atau SALAH pada kesalahan.
Catatan: Pada beberapa sistem, tidak mungkin membedakan antara kecocokan kosong dan kesalahan.

Periksa juga pertanyaan ini: Why count (false) return 1?

trante
sumber
1

Sejak variabel diuraikan sebagai negatif akan kembali int(1)dengancount()

Saya lebih suka ($array === [] || !$array)menguji array kosong.

Ya, kita harus mengharapkan larik kosong, tetapi kita seharusnya tidak mengharapkan implementasi yang baik pada fungsi tanpa tipe kembalian yang dipaksakan.

Contoh dengan count()

var_dump(count(0));
> int(1)
var_dump(count(false));
> int(1)
Sdlion
sumber
0

Saya membuat ulang pikiran saya, terima kasih.

Oke, tidak ada perbedaan antara penggunaan emptydan count. Secara teknis, countharus digunakan untuk array, dan emptybisa digunakan untuk array serta string. Jadi dalam banyak kasus, mereka dapat dipertukarkan dan jika Anda melihat dokumen php, Anda akan melihat daftar saran countjika Anda berada di emptydan sebaliknya.

Sarfraz
sumber