Co jest szybsze i lepsze, aby określić, czy klucz tablicy istnieje w PHP?

157

Rozważ te 2 przykłady ...

$key = 'jim';

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

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

Chciałbym wiedzieć, czy któryś z nich jest lepszy. Zawsze używałem pierwszego, ale widziałem, jak wiele osób używa drugiego przykładu na tej stronie.

Więc co jest lepsze? Szybciej? Jaśniejszy zamiar?

Alex
źródło
Nie przeprowadziłem żadnych testów porównawczych, nie. Powinienem to zrobić przed zapytaniem?
Alex
4
issetnigdy nie zachowa się dokładnie tak samo array_key_exists, przykładowy kod, który rzekomo sprawia, że ​​zachowuje się identycznie, rzuca Notice, jeśli klucz nie istnieje.
deceze
O co chodzi in_array? maettig.com/1397246220
DanMan
1
@DanMan, in_arrayto O(n)dlatego, że nie sprawdza wartości kluczy. Prawie zawsze będą wolniejsze, chyba że twój njest bardzo mały.
Pacerier
Dlaczego nie $array[$key] === null?
Pacerier

Odpowiedzi:

237

isset()jest szybszy, ale to nie to samo co array_key_exists().

array_key_exists()wyłącznie sprawdza, czy klucz istnieje, nawet jeśli wartością jest NULL.

Natomiast isset()zwróci, falsejeśli klucz istnieje i ma wartość NULL.

Richard Levasseur
źródło
5
Czy masz określone zasoby, z których roszczenie jest szybsze?
Francesco Pasa
@Francesco Pasa Pomyśl o tym trochę. issetnie jest funkcją przeszukiwania tablicy, sprawdza jedynie obecność zmiennej w tablicy symboli i nie będzie iterować po tablicy. array_key_existsz drugiej strony będzie iterować / wyszukiwać klucze w pierwszym wymiarze określonej tablicy.
Deszcz
@Rain Jestem prawie pewien, array_key_exists()że sprawdzi tylko, czy klucz znajduje się w tablicy, co oznacza, że ​​nie wykona wyszukiwania, ponieważ jest to tabela skrótów.
Francesco Pasa
@FrancescoPasa Cóż, „szukaj kluczy” jest tym, co mówi dokumentacja PHP. Poza tym nie potrafię stwierdzić, czy „wyszukiwanie” oznacza dla nich coś zupełnie innego niż to, co dla mnie znaczy.
Deszcz
32

Jeśli jesteś zainteresowany testami, które ostatnio wykonałem:

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

Podsumowanie:

| 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
źródło
WAŻNE: wykryto, że timing arrayKeyExists jest bardzo zły - sprawdzał wartość, a nie klucz - podążaj za tym linkiem, aby sprawdzić poprawioną synchronizację w 7.1, co jest znacznie lepsze. (Byłoby również lepsze we wcześniejszych wersjach php, gdyby Populus powtórzył ten test.)
ToolmakerSteve
19

Cóż, główna różnica polega na tym, isset()że nie zwracają one truekluczy tablic, które odpowiadają wartości null, podczas gdy array_key_exists()tak.

Przeprowadzenie małego testu porównawczego pokazuje, isset()że jest szybszy, ale może nie być całkowicie dokładny.

CMS
źródło
1
Czy możesz ponownie uruchomić test porównawczy z bardziej poprawnym "(isset ($ array [$ i]) || $ array [$ i] === null)"?
Tomalak
Aha, i czy mógłbyś zamieścić wskazanie, jaką różnicę w wydajności pokazują te dwa warianty? Dzięki!
Tomalak
1
@Tomalak, uruchomiłem sugerowany przez ciebie przykład i stwierdza, że ​​array_key_exists () jest szybsza niż isset () z || operator. codepad.org/5qyvS93x
alex
1
Up from the dead ... ale również ponownie przeprowadziłem test porównawczy i wprowadziłem poprawki, aby druga pętla for musiała zainicjować swój własny licznik i wyczyścić tablicę wyników. Pokazuje, że "isset || null" jest szybsze. codepad.org/Np6oPvgS
KyleWpppd
3
@Tomalak, isset($array[$i]) || $array[$i] === nullnie ma sensu, ponieważ wróci trueza każdym razem. Nigdy nie otrzymasz fałszu isset($array[$i]) || $array[$i] === nullniezależnie od danych wejściowych.
Pacerier
10

Chciałem dodać moje 2 centy do tego pytania, ponieważ brakowało mi środkowego wyjścia.

Jak już powiedziano isset(), obliczy wartość klucza, więc zwróci, falsejeśli ta wartość jest nullgdzie array_key_exists(), sprawdzi tylko, czy klucz istnieje w tablicy.


Przeprowadziłem prosty test porównawczy przy użyciu PHP 7, pokazane wyniki to czas potrzebny do zakończenia iteracji:

$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

Dodałem wyniki tej funkcji niestandardowej do tego testu porównawczego, aby zakończyć:

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

Jak widać i już powiedziano, isset()jest najszybszą metodą, ale może zwrócić fałsz, jeśli wartość jest null. Może to dać niepożądane rezultaty i zwykle należy go użyć, array_key_exists()jeśli tak jest.

Jest jednak środkowe wyjście i to jest używanie isset() || array_key_exists(). Ten kod generalnie używa szybszej funkcji isset()i jeśli isset() zwraca tylko fałsz, użyj array_key_exists()do walidacji. Pokazane w powyższej tabeli, jest tak samo szybkie, jak zwykłe wywołanie isset().

Tak, trochę więcej jest pisanie, a zawijanie go w funkcję jest wolniejsze, ale o wiele łatwiejsze. Jeśli potrzebujesz tego do wydajności, sprawdzania dużych zbiorów danych itp., Zapisz go w całości, w przeciwnym razie, jeśli jest to jednorazowe użycie, bardzo niewielkie obciążenie funkcji array_key_isset()jest pomijalne.

Xorifelse
źródło
7

Z PHP 7 daje możliwość korzystania z Null Coalescing Operator .

Operator koalescencji zerowej (??) został dodany jako cukier syntaktyczny w typowym przypadku potrzeby użycia trójskładnika w połączeniu z isset (). Zwraca swój pierwszy operand, jeśli istnieje i nie ma wartości NULL; w przeciwnym razie zwraca swój drugi operand.

Więc teraz możesz przypisać wartość domyślną na wypadek, gdyby wartość była pusta lub jeśli klucz nie istnieje:

$var = $array[$key] ?? 'default value'
Jan
źródło
6

istnieje różnica w stosunku do php.net, którą przeczytasz:

isset () nie zwraca TRUE dla kluczy tablicy, które odpowiadają wartości NULL, podczas gdy array_key_exists () tak.

Bardzo nieformalny test pokazuje, array_key_exists()że jest około 2,5 razy wolniejszy niżisset()

Scott Evernden
źródło
3

Łączenie isset()i is_null()daje najlepszą wydajność w stosunku do innych funkcji, takich jak: array_key_exists(), isset(), isset()+ array_key_exists(), is_null(), isset()+ is_null(), jedynym problemem tutaj jest funkcją nie tylko return false jeśli klucz nie istnieje, ale nawet klucz istnieje i ma wartość zerową.

Skrypt testowy:

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

Źródło : http://www.zomeoff.com/php-fast-way-to-determine-a-key-elements-existance-in-an-array/

H Aßdøµ
źródło
1

Co do „szybszego”: Spróbuj (moje pieniądze są włączone array_key_exists() , ale nie mogę tego teraz wypróbować).

Co do „jaśniejszego zamiaru”: array_key_exists()

Tomalak
źródło
3
isset () jest faktycznie znacznie szybsze, jeśli nie przejmujesz się zachowaniem zerowym (zobacz randombenchmarks.com/?p=29 ).
Matt Kantor
0

Oczywiście drugi przykład jest jaśniejszy w zamiarze, nie ma co do tego wątpliwości. Aby dowiedzieć się, co robi przykład # 1, musisz zapoznać się z idiosynkracjami inicjalizacji zmiennych PHP - a wtedy przekonasz się, że działa on inaczej dla wartości null i tak dalej.

Co do tego, która jest szybsza - nie zamierzam spekulować - uruchom albo w ciasnej pętli kilkaset tysięcy razy na swojej wersji PHP, a przekonasz się :)

Mihai Limbășan
źródło
-2

Twój kod isset($array[$i]) || $array[$i] === null,, zwróci wartość true w każdym przypadku, nawet jeśli klucz nie istnieje (i zwróci informację o niezdefiniowanym indeksie). Aby uzyskać najlepszą wydajność, chceszif (isset($array[$key]) || array_key_exists($key,$array)){doWhatIWant();}

Gator
źródło
1
Jedyny moment $array[$i] === nullzostanie wykonany, gdy $ i istnieje w tablicy i ma wartość NULL ..
Niclas Larsson