Що швидше і краще визначити, чи існує ключ масиву в PHP?


157

Розглянемо ці 2 приклади ...

$key = 'jim';

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

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

Мені цікаво дізнатись, чи краще щось із них. Я завжди використовував перший, але бачив, як багато людей використовують другий приклад на цьому сайті.

Отже, що краще? Швидше? Чіткіший намір?


Я не виконував жодних орієнтирів, ні. Чи повинен я перед тим, як запитати?
alex

4
issetніколи не буде поводитись так, як array_key_existsприклад коду, який нібито змушує його поводитись однаково, кидає повідомлення, якщо ключ не існує.
деле

Про що in_array? maettig.com/1397246220
DanMan

1
@DanMan, in_arrayтому O(n)що він перевіряє значення, а не ключі. Вони майже завжди будуть повільнішими, якщо ваш nнадзвичайно маленький.
Pacerier

Чому ні $array[$key] === null?
Pacerier

Відповіді:


237

isset()швидше, але це не те саме, що array_key_exists().

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

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


6
Чи є у вас конкретні ресурси, які стверджують, що накладення коштів відбувається швидше?
Франческо Паса

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

ВАЖЛИВО: тимчасове встановлення arrayKeyExists було виявлено дуже неправильним - воно перевіряло значення не ключове - перейдіть за цим посиланням для переглянутого часу в 7.1, що набагато краще. (Також краще в більш ранніх версіях PHP, якщо Populus переробив цей тест.)
ToolmakerSteve

19

Що ж, головна відмінність полягає в тому, що isset()він не повертається trueдля ключів масиву, що відповідають нульовому значенню, в той час як array_key_exists()це робить.

Запуск невеликого еталону показує, що isset()він швидший, але може бути не зовсім точним.


1
Чи можете ви знову запустити орієнтир з більш правильним "(isset ($ array [$ i]) || $ array [$ i] === null)"?
Томалак

О, а ви б опублікували вказівку, яка різниця в продуктивності показує два варіанти? Дякую!
Томалак

1
@Tomalak, я запустив приклад, який ви запропонували, і в ньому йдеться про те, що array_key_exists () швидше, ніж isset () з || оператор. codepad.org/5qyvS93x
alex

1
Вгору від мертвих ... але я також повторно запустив орієнтир і зробив налаштування, щоб другий цикл повинен ініціалізувати власний лічильник і очистити масив результатів. Він показує, що "isset || null" стає швидшим. codepad.org/Np6oPvgS
KyleWpppd

3
@Tomalak, isset($array[$i]) || $array[$i] === nullне має сенсу, тому що він повернеться trueза кожен випадок. Ви ніколи не помилитесь isset($array[$i]) || $array[$i] === nullнезалежно від введених даних.
Pacerier

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()це найшвидший метод, але він може повернути помилкове значення, якщо це значення null. Це може дати небажані результати, і зазвичай це слід використовувати, array_key_exists()якщо це так.

Однак є середній вихід, який використовується isset() || array_key_exists(). Цей код, як правило, використовує більш швидку функцію, isset()і якщо isset() повертає помилковий, тоді використовуйте array_key_exists()для перевірки. Показано в таблиці вище, його так само швидко, як і просто дзвінки isset().

Так, писати трохи більше, а згортати їх у функції - це повільніше, але набагато простіше. Якщо вам це потрібно для продуктивності, перевірки великих даних тощо, випишіть їх повністю, інакше, якщо його використання одноразово, то дуже незначні накладні витрати у функції array_key_isset()незначні.


7

Завдяки Php 7 надається можливість використання оператора Null Coalescing .

Оператор нульового згортання (??) доданий як синтаксичний цукор для звичайного випадку, коли потрібно використовувати трійку спільно з 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/


1

Щодо "швидшого": спробуйте (мої гроші зараз array_key_exists(), але зараз не можу спробувати).

Щодо "яснішого у намірі": array_key_exists()


3
isset () насправді значно швидше, якщо ви не переймаєтесь нульовою поведінкою (див. randombenchmarks.com/?p=29 ).
Метт Кантор

0

Очевидно, що другий приклад є чіткішим у намірі, про це не йдеться. Щоб зрозуміти, що робить приклад №1, вам потрібно ознайомитись із ідіосинкратіями змінної PHP, і тоді ви дізнаєтесь, що вона діє по-різному для нульових значень тощо.

Що стосується того, що швидше - я не збираюся міркувати - запустіть або в тугий цикл кілька сотень тисяч разів на вашій PHP-версії, і ви дізнаєтесь :)


-2

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


1
Єдиний час, $array[$i] === nullякий буде виконано, це коли $ i існує в масиві і має значення NULL ..
Niclas Larsson
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.