本文目的
前幾天工作中,需要頻繁判斷數組中的鍵值對是否存在,起初使用的”!empty($arr[‘key’])”來判斷,覺得這樣讀起來比較舒服,但是寫出的代碼無法通過單元測試(單元測試太好了)。排查很久,終於發現,當$arr[‘key’] == 0時,empty仍然返回true,這樣破壞了業務邏輯!
今天終於有空,就將判斷數組鍵值對存在的方法查閱了一下,記錄於此,作爲備忘。
一個例子
猜猜看,下面的例子會輸出什麼?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<?php $a = array( 'a' =>1, 'b' =>0, 'c' =>NULL); echo 'a test by empty: ' , empty($a[ 'a' ]) ? 'not exist' : 'exist' , PHP_EOL; echo 'a test by isset: ' , isset($a[ 'a' ]) ? 'exist' : 'not exist' , PHP_EOL; echo 'a test by array_key_exists: ' , array_key_exists( 'a' , $a) ? 'exist' : 'not exist' , PHP_EOL, PHP_EOL; echo 'b test by empty: ' , empty($a[ 'b' ]) ? 'not exist' : 'exist' , PHP_EOL; echo 'b test by isset: ' , isset($a[ 'b' ]) ? 'exist' : 'not exist' , PHP_EOL; echo 'b test by array_key_exists: ' , array_key_exists( 'b' , $a) ? 'exist' : 'not exist' , PHP_EOL, PHP_EOL; echo 'c test by empty: ' , empty($a[ 'c' ]) ? 'not exist' : 'exist' , PHP_EOL; echo 'c test by isset: ' , isset($a[ 'c' ]) ? 'exist' : 'not exist' , PHP_EOL; echo 'c test by array_key_exists: ' , array_key_exists( 'c' , $a) ? 'exist' : 'not exist' , PHP_EOL, PHP_EOL; |
輸出結果如下:
========================================================
a test by empty: exist
a test by isset: exist
a test by array_key_exists: exist
b test by empty: not exist
b test by isset: exist
b test by array_key_exists: exist
c test by empty: not exist
c test by isset: not exist
c test by array_key_exists: exist
========================================================
注意紅色高亮部分
三種方式的語法區別
- empty: 參數爲0或爲NULL時(如上面列子),empty均返回TRUE,詳細情況可以參見empty官方手冊
- isset: 參數爲NULL時,返回FALSE,0與NULL在PHP中是有區別的,isset(0)返回TRUE
- array_key_exists: 純粹的判斷數組鍵值對是否存在,無論值是多少
所以,從準確性的角度來看,array_key_exists是最準確的!
三種方式的性能比較
從網上拿到一組數據,參見這裏或參考資料,如下所示:
For a small array:
array_key_exists: float(0.18357992172241)
empty: float(0.072798013687134)
isset: float(0.070242881774902)
For a relative big array:
array_key_exists: float(0.57489585876465)
empty: float(0.0068421363830566)
isset: float(0.0069410800933838)
可以看到在大數據情況下,empty和isset的性能比array_key_exists快了2個數量級,差別還是很大。如果頻繁判斷,還是需要優化。產生這麼大性能差別的原因,個人猜測,可能是isset和empty作爲php語法結構不是函數,php解釋器做了優化,而array_key_exists作爲函數,沒有相關優化。具體原因,有待通過源碼考究。
三種方式的使用建議
(鑑於empty與isset性能類似,但是isset準確性較高,這裏就只比較isset與array_key_exists)
- 如果數組不可能出現值爲NULL的情況,建議使用isset
- 如果數組中經常出現值爲NULL的情況,建議使用array_key_exists
- 如果數組中可能出現值爲NULL,但是較少的情況,建議結合isset與array_key_exists使用,如“if (isset($arr[‘key’]) || array_key_exists(‘key’, $arr)){/*do somthing*/}”。此方法兼顧了性能和準確性,但是代碼變長了。
參考資料