PHP'de bir dizi anahtarının var olup olmadığını belirlemek için daha hızlı ve daha iyi olan nedir?


157

Bu 2 örneği ele alalım ...

$key = 'jim';

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

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

Bunlardan birinin daha iyi olup olmadığını bilmekle ilgileniyorum. Her zaman ilkini kullandım, ancak birçok insanın bu sitede ikinci örneği kullandığını gördüm.

Peki hangisi daha iyi? Daha hızlı? Daha net niyet?


Hiçbir ölçüt çalıştırmadım, hayır. Sormadan önce almalıyım?
alex

4
issethiçbir zaman tam olarak array_key_existsaynı şekilde davranmayacaktır, sözde onu aynı şekilde davranan kod örneği, anahtar yoksa bir Uyarı atar.
deceze

Ne olmuş in_array? maettig.com/1397246220
DanMan

1
@DanMan, in_arrayolduğu O(n)o değerleri değil tuşları denetler çünkü. Son nderece küçük olmadıkça neredeyse her zaman daha yavaş olacaklardır .
Pacerier

Neden olmasın $array[$key] === null?
Pacerier

Yanıtlar:


237

isset()daha hızlı, ancak aynı değil array_key_exists().

array_key_exists()değer olsa bile, anahtarın var olup olmadığını tamamen kontrol eder NULL.

Oysa anahtar varsa ve değer ise isset()geri döner .falseNULL


6
İssetin daha hızlı olduğunu iddia eden belirli kaynaklarınız var mı?
Francesco Pasa

@Francesco Pasa Biraz düşünün. issetbir dizi arama işlevi değildir, yalnızca sembol tablosunda bir değişkenin varlığını kontrol eder ve dizi üzerinde yinelenmez. array_key_existsÖte yandan belirtilen dizinin ilk boyutundaki anahtarları yineleyecek / arayacaktır.
Yağmur

@Rain eminim array_key_exists()sadece anahtar dizide olup olmadığını kontrol edecek, bu bir karma tablo olduğu için bir arama yapmayacak anlamına gelir.
Francesco Pasa

@FrancescoPasa Eh, "anahtarları ara" PHP belgelerinin söylediği şeydir. Bunun dışında, onlara "ara" ifadesinin benim için ne anlama geldiğinden tamamen farklı bir şey ifade edip etmediğini söyleyemem.
Yağmur

32

Son zamanlarda yaptığım bazı testlerle ilgileniyorsanız:

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

Özet:

| 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%

ÖNEMLİ: arrayKeyExists zamanlamasının çok yanlış olduğu keşfedildi - anahtar değil değeri kontrol ediyordu - 7.1'de revize edilmiş zamanlama için bu bağlantıyı takip edin, çok daha iyi. (Populus bu testi tekrarladıysa, önceki php sürümlerinde de daha iyi olurdu.)
ToolmakerSteve

19

Asıl fark, boş bir değere karşılık gelen dizi anahtarları için isset()geri dönmeyecek .truearray_key_exists()

Küçük bir karşılaştırma ölçütü çalıştırmak , isset()bunun daha hızlı olduğunu ancak tamamen doğru olmayabileceğini gösterir .


1
Karşılaştırmayı daha doğru "(isset ($ array [$ i]) || $ array [$ i] === null)" ile tekrar çalıştırabilir misiniz?
Tomalak

Oh, ve iki varyantın ne kadar performans farkı gösterdiğine dair bir gösterge gönderir misiniz? Teşekkürler!
Tomalak

1
@Tomalak, önerdiğiniz örneği çalıştırdım ve array_key_exists () 'nin || ile isset ()' den daha hızlı olduğunu belirtir Şebeke. codepad.org/5qyvS93x
alex

1
Öldürüldüğünden ... ama ben de karşılaştırmayı yeniden çalıştırdım ve bir tweak yaptım, böylece döngü için ikinci, kendi sayacını başlatmalı ve sonuç dizisini temizlemeli. "İsset || null" ın daha hızlı olduğunu gösterir. codepad.org/Np6oPvgS
KyleWpppd

3
@Tomalak, isset($array[$i]) || $array[$i] === nullmantıklı değil çünkü trueher dava için geri dönecek . isset($array[$i]) || $array[$i] === nullGirdiler ne olursa olsun asla yanlış olmayacaksınız .
Pacerier

10

Orta yoldan kaçtığım için bu soruya 2 sent eklemek istedim.

Daha önce de belirtildiği gibi isset(), anahtarın değerini değerlendirecektir, böylece bu falsedeğer nullnerede olursa dönecektir array_key_exists(), ancak anahtarın dizide var olup olmadığını kontrol edecektir.


PHP 7 kullanarak basit bir kıyaslama çalıştırdım, gösterilen sonuçlar yinelemeyi bitirmek için gereken süredir:

$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

Bu özel fonksiyonun sonuçlarını bu kıyaslama ile de tamamladım:

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

Görüldüğü ve zaten söylendiği gibi isset()en hızlı yöntemdir, ancak değer ise yanlış dönebilir null. Bu istenmeyen sonuçlar verebilir ve genellikle array_key_exists()durum böyle ise kullanılmalıdır.

Ancak orta çıkış yolu var ve kullanıyor isset() || array_key_exists(). Bu kod genellikle daha hızlı işlevi kullanır isset()ve yalnızca false değerini isset() döndürürse doğrulamak için kullanın . Yukarıdaki tabloda gösterildiği gibi, açıkça arama kadar hızlıdır .array_key_exists()isset()

Evet, bir fonksiyona yazmak ve sarmak biraz daha yavaş ama çok daha kolay. Performans, büyük veri, vb kontrol etmek için buna ihtiyacınız varsa, tam olarak yazın, aksi takdirde, fonksiyonda çok küçük bir ek yükün array_key_isset()ihmal edilebilir olması durumunda 1 kez kullanım .


7

Php 7 ile Null Birleştirme Operatörü kullanma imkanı verir .

Boş birleştirme operatörü (??), yaygın olarak isset () ile birlikte üçlü kullanılması gerektiğinde sözdizimsel şeker olarak eklenmiştir. Varsa ve NULL değilse ilk işlenenini döndürür; aksi takdirde ikinci işlenişini döndürür.

Böylece, değerin boş olması veya anahtarın bulunmaması durumunda varsayılan bir değer atayabilirsiniz:

$var = $array[$key] ?? 'default value'

6

php.net'ten okuyacağınız bir fark var :

isset (), NULL değerine karşılık gelen dizi anahtarları için TRUE döndürmez, array_key_exists () ise döndürür.

Çok gayri resmi bir test, array_key_exists()yaklaşık 2,5 kat daha yavaş olduğunu göstermektedir.isset()


3

Birleştiren isset()ve is_null()benzeri diğer fonksiyonlar karşı en iyi performansı vermek: array_key_exists(), isset(), isset()+ array_key_exists(), is_null(), isset()+ is_null(), burada tek sorun anahtarı yoksa fonksiyon return false kalmayacak, ama hatta anahtar var olur ve boş değere sahiptir.

Karşılaştırma komut dosyası:

<?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>";
?>

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


1

"Daha hızlı" gelince: Deneyin (param açık array_key_exists(), ama şimdi deneyemiyorum).

"Niyette daha net" ile ilgili olarak: array_key_exists()


3
Eğer null davranışı umursamıyorsanız isset () aslında çok daha hızlıdır (bkz. randombenchmarks.com/?p=29 ).
Matt Kantor

0

Açıkçası, ikinci örnek niyeti daha açıktır, bununla ilgili bir soru yoktur. Örnek 1'in ne yaptığını anlamak için PHP'nin değişken başlatma kimlik bilgilerine aşina olmanız gerekir - ve sonra boş değerler için farklı çalıştığını öğrenirsiniz.

Hangisi daha hızlı - spekülasyon yapmak istemiyorum - PHP sürümünüzde birkaç yüz bin kez sıkı bir döngüde çalıştırın ve öğreneceksiniz :)


-2

isset($array[$i]) || $array[$i] === nullAnahtarınız olmasa bile, kodunuz her durumda true değerini döndürür (ve tanımlanmamış bir dizin bildirimi verir). En iyi performans için istediğiniz şeyif (isset($array[$key]) || array_key_exists($key,$array)){doWhatIWant();}


1
Tek $array[$i] === nullidam yürütülecek $ i dizide var ve NULL değerine sahip olduğunda ..
Niclas Larsson
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.