Was ist schneller und besser, um festzustellen, ob in PHP ein Array-Schlüssel vorhanden ist?

157

Betrachten Sie diese 2 Beispiele ...

$key = 'jim';

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

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

Ich bin daran interessiert zu wissen, ob eines davon besser ist. Ich habe immer das erste Beispiel verwendet, aber viele Leute haben das zweite Beispiel auf dieser Site verwendet.

Also, was ist besser? Schneller? Klarere Absicht?

Alex
quelle
Ich habe keine Benchmarks durchgeführt, nein. Sollte ich haben, bevor ich frage?
Alex
4
issetwird sich niemals genau so verhalten, wie array_key_existsdas Codebeispiel, das angeblich dazu führt, dass es sich identisch verhält, einen Hinweis auslöst, wenn der Schlüssel nicht existiert.
Täuschung
Was ist mit in_array? maettig.com/1397246220
DanMan
1
@DanMan, in_arrayist , O(n)weil sie die Werte nicht die Schlüssel überprüft. Sie werden fast immer langsamer sein, es sei denn, Sie nsind extrem klein.
Pacerier
Warum nicht $array[$key] === null?
Pacerier

Antworten:

237

isset()ist schneller, aber es ist nicht dasselbe wie array_key_exists().

array_key_exists()prüft lediglich, ob der Schlüssel vorhanden ist, auch wenn der Wert ist NULL.

Wobei zurückgegeben isset()wird, falsewenn der Schlüssel existiert und der Wert ist NULL.

Richard Levasseur
quelle
5
Haben Sie bestimmte Ressourcen, die behaupten, dass isset schneller ist?
Francesco Pasa
@Francesco Pasa Denk einfach ein bisschen darüber nach. issetist keine Array-Suchfunktion, sondern überprüft nur das Vorhandensein einer Variablen in der Symboltabelle und iteriert nicht über das Array. array_key_existsAuf der anderen Seite wird nach den Schlüsseln in der ersten Dimension des angegebenen Arrays iteriert / gesucht.
Regen
@Rain Ich bin mir ziemlich sicher, array_key_exists()dass nur geprüft wird, ob sich der Schlüssel im Array befindet, was bedeutet, dass keine Suche durchgeführt wird, da es sich um eine Hash-Tabelle handelt.
Francesco Pasa
@FrancescoPasa Nun, "Suche nach den Schlüsseln" heißt es in der PHP-Dokumentation. Davon abgesehen kann ich nicht sagen, ob "Suchen" für sie etwas völlig anderes bedeutet als für mich.
Regen
32

Wenn Sie an einigen Tests interessiert sind, die ich kürzlich durchgeführt habe:

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

Zusammenfassung:

| 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
quelle
WICHTIG: Es wurde festgestellt, dass das Timing von arrayKeyExists sehr falsch ist - es wurde der Wert nicht der Schlüssel überprüft - folgen Sie diesem Link für das überarbeitete Timing in 7.1, was viel besser ist. (Wäre auch in früheren PHP-Versionen besser, wenn Populus diesen Test wiederholen würde.)
ToolmakerSteve
19

Nun, der Hauptunterschied besteht darin , dass isset()keine Rück truefür Array - Schlüssel , die entsprechen einem Nullwert, während der array_key_exists()Fall ist.

Das Ausführen eines kleinen Benchmarks zeigt, dass isset()es schneller ist, aber möglicherweise nicht ganz genau.

CMS
quelle
1
Können Sie den Benchmark erneut mit dem korrekteren "(isset ($ array [$ i]) || $ array [$ i] === null)" ausführen?
Tomalak
Oh, und würden Sie einen Hinweis darauf geben, wie viel Leistungsunterschied die beiden Varianten aufweisen? Vielen Dank!
Tomalak
1
@Tomalak, ich habe das von Ihnen vorgeschlagene Beispiel ausgeführt und es besagt, dass array_key_exists () mit || schneller ist als isset () Operator. codepad.org/5qyvS93x
alex
1
Up from the dead ... aber ich habe auch den Benchmark erneut ausgeführt und eine Optimierung vorgenommen, sodass die zweite for-Schleife ihren eigenen Zähler initialisieren und das Ergebnisarray löschen muss. Es zeigt, dass "isset || null" schneller ist. codepad.org/Np6oPvgS
KyleWpppd
3
@Tomalak, isset($array[$i]) || $array[$i] === nullmacht keinen Sinn, weil es truefür jeden Fall zurückkehren wird. Sie werden niemals falsch sein, isset($array[$i]) || $array[$i] === nullunabhängig von den Eingaben.
Pacerier
10

Ich wollte meine 2 Cent zu dieser Frage hinzufügen, da mir ein Mittelweg fehlte.

Wie bereits erwähnt, isset()wird der Wert des Schlüssels ausgewertet, sodass zurückgegeben wird, falsewenn dieser Wert angegeben ist. nullDort array_key_exists()wird nur geprüft, ob der Schlüssel im Array vorhanden ist.


Ich habe einen einfachen Benchmark mit PHP 7 durchgeführt. Die angezeigten Ergebnisse sind die Zeit, die zum Beenden der Iteration benötigt wurde:

$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

Ich habe die Ergebnisse dieser benutzerdefinierten Funktion auch zur Vervollständigung mit diesem Benchmark hinzugefügt:

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

Wie gesehen und bereits gesagt isset()ist die schnellste Methode, kann aber false zurückgeben, wenn der Wert ist null. Dies könnte zu unerwünschten Ergebnissen führen und sollte normalerweise verwendet werden, array_key_exists()wenn dies der Fall ist.

Es gibt jedoch einen Mittelweg und das nutzt isset() || array_key_exists(). Dieser Code wird unter Verwendung der Regel die schnellere Funktion isset()und wenn isset() false zurück nur dann verwenden , array_key_exists()zu validieren. In der obigen Tabelle ist es genauso schnell wie ein klarer Anruf isset().

Ja, es ist ein bisschen mehr zu schreiben und es in eine Funktion zu packen ist langsamer, aber viel einfacher. Wenn Sie dies für die Leistung, das Überprüfen von Big Data usw. benötigen, schreiben Sie es vollständig aus. Andernfalls ist der sehr geringe Funktionsaufwand array_key_isset()vernachlässigbar , wenn es sich um eine einmalige Verwendung handelt.

Xorifelse
quelle
7

Mit Php 7 gibt es die Möglichkeit, den Null Coalescing Operator zu verwenden .

Der Null-Koaleszenz-Operator (??) wurde als syntaktischer Zucker für den allgemeinen Fall hinzugefügt, dass in Verbindung mit isset () ein Ternär verwendet werden muss. Es gibt seinen ersten Operanden zurück, wenn er existiert und nicht NULL ist. Andernfalls wird der zweite Operand zurückgegeben.

Jetzt können Sie einen Standardwert zuweisen, falls der Wert null ist oder der Schlüssel nicht vorhanden ist:

$var = $array[$key] ?? 'default value'
John
quelle
6

Es gibt einen Unterschied zu php.net, den Sie lesen werden:

isset () gibt für Array-Schlüssel, die einem NULL-Wert entsprechen, nicht TRUE zurück, während array_key_exists () dies tut.

Ein sehr informeller Test zeigt array_key_exists(), dass er etwa 2,5-mal langsamer ist alsisset()

Scott Evernden
quelle
3

Die Kombination isset()und is_null()gibt die beste Leistung gegen andere Funktionen wie: array_key_exists(), isset(), isset()+ array_key_exists(), is_null(), isset()+ is_null(), hier das einzige Problem ist die Funktion nur falsch es wird bestätigt , wenn der Schlüssel nicht vorhanden ist , sondern auch der Schlüssel exist und hat einen Nullwert.

Benchmark-Skript:

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

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

H Aßdøµ
quelle
1

Was "schneller" betrifft: Probieren Sie es aus (mein Geld ist an array_key_exists(), aber ich kann es momentan nicht versuchen).

Zu "klarer in der Absicht": array_key_exists()

Tomalak
quelle
3
isset () ist tatsächlich erheblich schneller, wenn Sie sich nicht für das Nullverhalten interessieren (siehe randombenchmarks.com/?p=29 ).
Matt Kantor
0

Offensichtlich ist das zweite Beispiel klarer in der Absicht, es gibt keine Frage. Um herauszufinden, was Beispiel 1 tut, müssen Sie mit den variablen Initialisierungs-Eigenheiten von PHP vertraut sein - und dann werden Sie feststellen, dass es für Nullwerte anders funktioniert und so weiter.

Was schneller ist - ich habe nicht vor zu spekulieren - laufen Sie einige hunderttausend Mal in einer engen Schleife auf Ihrer PHP-Version und Sie werden es herausfinden :)

Mihai Limbășan
quelle
-2

Ihr Code gibt isset($array[$i]) || $array[$i] === nullin jedem Fall true zurück, auch wenn der Schlüssel nicht vorhanden ist (und einen undefinierten Indexhinweis liefert). Für die beste Leistung möchten Sieif (isset($array[$key]) || array_key_exists($key,$array)){doWhatIWant();}

Alligator
quelle
1
Die einzige Zeit $array[$i] === null, die ausgeführt wird, ist, wenn $ i im Array vorhanden ist und den Wert NULL hat.
Niclas Larsson