Что быстрее и лучше определить, существует ли ключ массива в PHP?

157

Рассмотрим эти 2 примера ...

$key = 'jim';

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

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

Мне интересно знать, если один из них лучше. Я всегда использовал первый, но многие люди видели второй пример на этом сайте.

Итак, что лучше? Быстрее? Более четкие намерения?

Алекс
источник
Я не проводил никаких тестов, нет. Должен ли я иметь перед тем, как спросить?
Алекс
4
issetникогда не будет вести себя точно так же array_key_exists, пример кода, который предположительно заставляет его вести себя одинаково, выдает уведомление, если ключ не существует.
deceze
Как насчет in_array? maettig.com/1397246220
DanMan
1
@DanMan, in_arrayэто O(n)потому , что он проверяет не значения ключей. Они почти всегда будут медленнее, если только вы nне очень малы.
Пейсер
Почему нет $array[$key] === null?
Pacerier

Ответы:

237

isset()быстрее, но это не то же самое, что array_key_exists().

array_key_exists()чисто проверяет, существует ли ключ, даже если значение есть NULL.

Тогда как isset()вернетсяfalse если ключ существует и значение есть NULL.

Ричард Левассер
источник
6
У вас есть конкретные ресурсы, утверждающие, что isset быстрее?
Франческо Паса
@Francesco Pasa Подумай немного об этом. issetне является функцией поиска по массиву, она только проверяет наличие переменной в таблице символов и не выполняет итерацию по массиву. array_key_existsс другой стороны, будет выполнять итерацию / поиск ключей в первом измерении указанного массива.
дождь
@Rain Я уверен, array_key_exists()что проверю только, находится ли ключ в массиве, что означает, что он не будет выполнять поиск, поскольку это хеш-таблица.
Франческо Паша
@FrancescoPasa Ну, «поиск ключей» - это то, что написано в документации PHP. Кроме этого, я не могу сказать, означает ли «поиск» для них что-то совершенно иное, чем для меня.
дождь
32

Если вы заинтересованы в некоторых тестах, которые я сделал недавно:

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

Резюме:

| 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
источник
ВАЖНО: было обнаружено, что синхронизация arrayKeyExists была очень неправильной - она ​​проверяла значение, а не ключ - перейдите по этой ссылке для пересмотра синхронизации в 7.1, что намного лучше. (Также лучше в более ранних версиях PHP, если Populus переделал этот тест.)
ToolmakerSteve
19

Ну, главное отличие в том, что isset()не будет возвращаться trueдля ключей массива, которые соответствуют нулевому значению, а array_key_exists()делает.

Выполнение небольшого теста показывает, что isset()это быстрее, но может быть не совсем точно.

CMS
источник
1
Можете ли вы снова запустить тест с более правильным "(isset ($ array [$ i]) || $ array [$ i] === null)"?
Томалак
О, и не могли бы вы опубликовать указание на разницу в производительности, которую показывают два варианта? Спасибо!
Томалак
1
@ Tomalak, я запустил предложенный вами пример, и он утверждает, что array_key_exists () работает быстрее, чем isset () с || оператор. codepad.org/5qyvS93x
Алекс
1
Из мертвых ... но я также повторно запустил тест и сделал настройку, чтобы второй цикл for должен был инициализировать свой собственный счетчик и очистить массив результатов. Показывает, что isset || null быстрее. codepad.org/Np6oPvgS
KyleWpppd
3
@ Томалак, isset($array[$i]) || $array[$i] === nullне имеет смысла, потому что он вернется trueдля каждого случая. Вы никогда не ошибетесь isset($array[$i]) || $array[$i] === nullнезависимо от входных данных.
Пейсер
10

Я хотел добавить свои 2 цента по этому вопросу, так как мне не хватало среднего пути.

Как уже было сказано, isset()будет оцениваться значение ключа, поэтому он вернется, falseесли это значение будет nullгде array_key_exists(), только проверит, существует ли ключ в массиве.


Я выполнил простой тест с использованием PHP 7, показанный результат - это время, которое потребовалось для завершения итерации:

$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

Я добавил результаты этой пользовательской функции в этот тест, а также для завершения:

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

Как видно и уже сказано, isset()это самый быстрый метод, но он может вернуть false, если значение равно null. Это может дать нежелательные результаты, и обычно следует использовать, array_key_exists()если это так.

Однако есть средний выход, и он использует isset() || array_key_exists(). Этот код, как правило, использует более быструю функцию, isset()и если isset() возвращает только ложь, используйте array_key_exists()для проверки. Показанный в таблице выше, это так же быстро, как просто звонить isset().

Да, это немного больше, чтобы написать и обернуть его в функцию медленнее, но намного проще. Если вам это нужно для повышения производительности, проверки больших данных и т. Д., Запишите их полностью, в противном случае, если их однократное использование приводит к незначительным перегрузкам в работе array_key_isset(), незначительным.

Xorifelse
источник
7

С Php 7 дает возможность использовать Null Coalescing Operator .

Нулевой оператор объединения (??) был добавлен в качестве синтаксического сахара для общего случая необходимости использования троичного в сочетании с isset (). Возвращает свой первый операнд, если он существует и не равен NULL; в противном случае он возвращает свой второй операнд.

Так что теперь вы можете назначить значение по умолчанию в случае, если значение равно нулю или если ключ не существует:

$var = $array[$key] ?? 'default value'
Джон
источник
6

есть разница с php.net, которую вы прочтете:

isset () не возвращает TRUE для ключей массива, соответствующих значению NULL, в то время как array_key_exists () делает.

Очень неформальный тест показывает, array_key_exists()что он примерно в 2,5 раза медленнее, чемisset()

Скотт Эверден
источник
3

Объединение isset()и is_null()дают лучшую производительность против других функций , таких как: array_key_exists(), isset(), isset()+ array_key_exists(), is_null(), isset()+ is_null(), единственная проблема здесь функция не будет возвращать только ложь , если ключ не существует, но даже ключ существует , и имеет нулевое значение.

Контрольный скрипт:

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

Кредит : http://www.zomeoff.com/php-fast-way-to-determine-a-key-elements-existance-in-an-array/

H Aßdøµ
источник
1

Что касается «быстрее»: попробуйте (мои деньги включены array_key_exists(), но я не могу попробовать прямо сейчас).

Что касается «яснее в намерениях»: array_key_exists()

Томалак
источник
3
isset () на самом деле значительно быстрее, если вы не заботитесь о нулевом поведении (см. randombenchmarks.com/?p=29 ).
Мэтт Кантор
0

Очевидно, что второй пример более понятен, в этом нет сомнений. Чтобы выяснить, что делает пример № 1, вы должны быть знакомы с особенностями PHP инициализации переменных - и тогда вы обнаружите, что он работает по-разному для нулевых значений и так далее.

Что касается того, что быстрее - я не собираюсь спекулировать - запускайте несколько циклов несколько раз на вашей версии PHP, и вы узнаете :)

Михай Лимбакан
источник
-2

Ваш код, isset($array[$i]) || $array[$i] === nullбудет возвращать true в каждом случае, даже если ключ не существует (и выдает неопределенное уведомление об индексе). Для лучшей производительности, что вы хотели быif (isset($array[$key]) || array_key_exists($key,$array)){doWhatIWant();}

Gator
источник
1
Единственное время $array[$i] === nullбудет выполнено, когда $ i существует в массиве и имеет значение NULL ..
Никлас Ларссон