Apa yang lebih cepat dan lebih baik untuk menentukan apakah kunci array ada di PHP?

157

Perhatikan 2 contoh ini ...

$key = 'jim';

// example 1
if (isset($array[$key])) {
    // ...
}

// example 2    
if (array_key_exists($key, $array)) {
    // ...
}

Saya tertarik mengetahui apakah salah satu dari ini lebih baik. Saya selalu menggunakan yang pertama, tetapi telah melihat banyak orang menggunakan contoh kedua di situs ini.

Jadi, mana yang lebih baik? Lebih cepat? Niat yang lebih jelas?

alex
sumber
Saya belum menjalankan tolok ukur apa pun, tidak. Haruskah saya bertanya sebelum?
alex
4
issettidak akan pernah berperilaku persis seperti array_key_exists, contoh kode yang seharusnya membuatnya berperilaku secara identik melempar Pemberitahuan jika kunci tidak ada.
deceze
Bagaimana dengan in_array? maettig.com/1397246220
DanMan
1
@DanMan, in_arrayadalah O(n)karena memeriksa nilai bukan kunci. Mereka hampir selalu akan menjadi lebih lambat kecuali jika Anda nsangat kecil.
Pacerier
Mengapa tidak $array[$key] === null?
Pacerier

Jawaban:

237

isset()lebih cepat, tetapi tidak sama dengan array_key_exists().

array_key_exists()murni memeriksa apakah kunci ada, bahkan jika nilainya NULL.

Sedangkan isset()akan kembali falsejika kunci ada dan nilainya NULL.

Richard Levasseur
sumber
6
Apakah Anda memiliki sumber daya spesifik yang mengklaim bahwa penerbit lebih cepat?
Francesco Pasa
@ Francesco Pasa Pikirkan sedikit saja. issetbukan fungsi pencarian array, itu hanya memeriksa keberadaan variabel dalam tabel simbol dan tidak akan beralih pada array. array_key_existsdi sisi lain akan mengulangi / mencari kunci di dimensi pertama dari array yang ditentukan.
Hujan
@ Rain Aku cukup yakin array_key_exists()hanya akan memeriksa apakah kuncinya ada dalam array, yang berarti ia tidak akan melakukan pencarian karena ini adalah tabel hash.
Francesco Pasa
@FrancescoPasa Yah, "cari kunci" adalah apa yang dikatakan dokumentasi PHP. Selain itu, saya tidak tahu apakah "mencari" mereka berarti sesuatu yang sama sekali berbeda dengan apa artinya bagi saya.
Hujan
32

Jika Anda tertarik pada beberapa tes yang saya lakukan baru-baru ini:

https://stackoverflow.com/a/21759158/520857

Ringkasan:

| Method Name                              | Run time             | Difference
=========================================================================================
| NonExistant::noCheckingTest()            | 0.86004090309143     | +18491.315775911%
| NonExistant::emptyTest()                 | 0.0046701431274414   | +0.95346080503016%
| NonExistant::isnullTest()                | 0.88424181938171     | +19014.461681183%
| NonExistant::issetTest()                 | 0.0046260356903076   | Fastest
| NonExistant::arrayKeyExistsTest()        | 1.9001779556274      | +209.73055713%
Populus
sumber
PENTING: waktu arrayKeyExists ditemukan sangat salah - itu memeriksa nilai bukan kunci - ikuti tautan itu untuk waktu yang direvisi pada 7.1, yang jauh lebih baik. (Akan lebih baik di versi php sebelumnya, jika Populus membuat ulang tes itu.)
ToolmakerSteve
19

Nah, perbedaan utama adalah bahwa isset()tidak akan kembali trueuntuk kunci array yang sesuai dengan nilai nol, sementara itu array_key_exists()tidak.

Menjalankan patokan kecil menunjukkan bahwa isset()itu lebih cepat tetapi mungkin tidak sepenuhnya akurat.

CMS
sumber
1
Bisakah Anda menjalankan patokan lagi dengan yang lebih benar "(isset ($ array [$ i]) || $ array [$ i] === null)"?
Tomalak
Oh, dan apakah Anda akan memposting indikasi seberapa besar perbedaan kinerja yang ditunjukkan kedua varian? Terima kasih!
Tomalak
1
@ Tomalak, saya menjalankan contoh yang Anda sarankan, dan menyatakan bahwa array_key_exists () lebih cepat daripada isset () dengan || operator. codepad.org/5qyvS93x
alex
1
Naik dari kematian ... tapi saya juga menjalankan kembali patokan, dan membuat tweak sehingga loop kedua harus menginisialisasi counter itu sendiri dan menghapus hasil array. Ini menunjukkan "isset || null" lebih cepat. codepad.org/Np6oPvgS
KyleWpppd
3
@ Tomalak, isset($array[$i]) || $array[$i] === nulltidak masuk akal karena akan kembali trueuntuk setiap kasus. Anda tidak akan pernah salah dari isset($array[$i]) || $array[$i] === nullinput apa pun.
Pacerier
10

Saya ingin menambahkan 2 sen pada pertanyaan ini, karena saya kehilangan jalan tengah.

Seperti yang sudah mengatakan isset()akan mengevaluasi nilai kunci sehingga akan kembali falsejika nilai yang nullmana array_key_exists()hanya akan memeriksa apakah kunci ada dalam array.


Saya telah menjalankan patokan sederhana menggunakan PHP 7, hasil yang ditampilkan adalah waktu yang dibutuhkan untuk menyelesaikan iterasi:

$a = [null, true];

isset($a[0])                            # 0.3258841  - false
isset($a[1])                            # 0.28261614 - true
isset($a[2])                            # 0.26198816 - false

array_key_exists(0, $a)                 # 0.46202087 - true
array_key_exists(1, $a)                 # 0.43063688 - true
array_key_exists(2, $a)                 # 0.37593913 - false

isset($a[0]) || array_key_exists(0, $a) # 0.66342998 - true
isset($a[1]) || array_key_exists(1, $a) # 0.28389215 - true
isset($a[2]) || array_key_exists(2, $a) # 0.55677581 - false

array_key_isset(0, $a)                  # 1.17933798 - true
array_key_isset(1, $a)                  # 0.70253706 - true
array_key_isset(2, $a)                  # 1.01110005 - false

Saya telah menambahkan hasil dari fungsi kustom ini dengan tolok ukur ini untuk penyelesaian:

function array_key_isset($k, $a){
    return isset($a[$k]) || array_key_exists($k, $a);
}

Seperti yang terlihat dan sudah diceritakan isset()adalah metode tercepat tetapi dapat mengembalikan false jika nilainya null. Ini bisa memberikan hasil yang tidak diinginkan dan biasanya orang harus menggunakannya array_key_exists()jika itu masalahnya.

Namun ada jalan tengah dan itu menggunakan isset() || array_key_exists() . Kode ini umumnya menggunakan fungsi yang lebih cepat isset()dan jika isset() mengembalikan false saja maka gunakan array_key_exists()untuk memvalidasi. Ditampilkan pada tabel di atas, ini sama cepatnya dengan panggilan biasa isset().

Ya, ini sedikit lebih untuk menulis dan membungkusnya dalam suatu fungsi lebih lambat tetapi jauh lebih mudah. Jika Anda memerlukan ini untuk kinerja, memeriksa data besar, dll, tuliskan sepenuhnya, jika tidak, jika penggunaannya 1 kali, biaya overhead yang sangat kecil array_key_isset()dapat diabaikan.

Xorifelse
sumber
7

Dengan Php 7 memberi kemungkinan untuk menggunakan Null Coalescing Operator .

Operator penggabungan nol (??) telah ditambahkan sebagai gula sintaksis untuk kasus umum yang memerlukan penggunaan terner dalam hubungannya dengan isset (). Ini mengembalikan operan pertamanya jika ada dan bukan NULL; jika tidak mengembalikan operan keduanya.

Jadi sekarang Anda dapat menetapkan nilai default jika nilainya nol atau jika kunci tidak ada:

$var = $array[$key] ?? 'default value'
John
sumber
6

ada perbedaan dari php.net Anda akan membaca:

isset () tidak mengembalikan TRUE untuk kunci array yang sesuai dengan nilai NULL, sedangkan array_key_exists () tidak.

Tes yang sangat informal menunjukkan array_key_exists()sekitar 2,5 kali lebih lambat daripadaisset()

Scott Evernden
sumber
3

Menggabungkan isset()dan is_null()memberikan performa terbaik terhadap fungsi lain seperti: array_key_exists(), isset(), isset()+ array_key_exists(), is_null(), isset()+ is_null(), satu-satunya masalah di sini adalah fungsi tidak hanya akan mengembalikan false jika kunci tidak ada, tapi bahkan yang ada kunci dan memiliki nilai nol.

Skrip benchmark:

<?php
  $a = array('a' => 4, 'e' => null)

  $s = microtime(true); 
  for($i=0; $i<=100000; $i++) { 
    $t = (isset($a['a'])) && (is_null($a['a'])); //true 
    $t = (isset($a['f'])) && (is_null($a['f'])); //false
    $t = (isset($a['e'])) && (is_null($a['e']));; //false 
  } 

  $e = microtime(true); 
  echo 'isset() + is_null() : ' , ($e-$s)."<br><br>";
?>

Kredit : http://www.zomeoff.com/php-fast-way-to-determine-a-key-elements-existance-in-an-an-array/

H Aßdøµ
sumber
1

Adapun "lebih cepat": Cobalah (uang saya aktif array_key_exists(), tetapi saya tidak dapat mencobanya sekarang).

Adapun "lebih jelas dalam niat": array_key_exists()

Tomalak
sumber
3
isset () sebenarnya jauh lebih cepat jika Anda tidak peduli dengan perilaku nol (lihat randombenchmarks.com/?p=29 ).
Matt Kantor
0

Jelas contoh kedua lebih jelas maksudnya, tidak ada pertanyaan tentang itu. Untuk mengetahui apa yang dilakukan contoh # 1, Anda harus terbiasa dengan keanehan variabel inisialisasi PHP - dan kemudian Anda akan mengetahui bahwa itu berfungsi secara berbeda untuk nilai-nilai nol, dan seterusnya.

Mengenai mana yang lebih cepat - saya tidak bermaksud berspekulasi - jalankan dalam loop ketat beberapa ratus ribu kali pada versi PHP Anda dan Anda akan mengetahuinya :)

Mihai Limbășan
sumber
-2

Kode Anda isset($array[$i]) || $array[$i] === null,, akan mengembalikan true dalam setiap kasus, bahkan jika kunci tidak ada (dan menghasilkan pemberitahuan indeks yang tidak ditentukan). Untuk kinerja terbaik, apa yang Anda inginkan adalahif (isset($array[$key]) || array_key_exists($key,$array)){doWhatIWant();}

Gator
sumber
1
Satu-satunya waktu $array[$i] === nullakan dieksekusi adalah ketika $ i ada dalam array dan memiliki nilai NULL ..
Niclas Larsson