Quoi de plus rapide et de meilleur pour déterminer si une clé de tableau existe en PHP?

157

Considérez ces 2 exemples ...

$key = 'jim';

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

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

Je suis intéressé à savoir si l'un ou l'autre est meilleur. J'ai toujours utilisé le premier, mais j'ai vu beaucoup de gens utiliser le deuxième exemple sur ce site.

Alors, quel est le meilleur? Plus rapide? Une intention plus claire?

Alex
la source
Je n'ai pas exécuté de benchmarks, non. Dois-je avoir avant de demander?
alex
4
issetne se comportera jamais exactement comme array_key_exists, l'exemple de code qui est censé le faire se comporter de manière identique lance un avis si la clé n'existe pas.
deceze
Et quoi in_array? maettig.com/1397246220
DanMan
1
@DanMan, in_arrayc'est O(n)parce qu'il vérifie les valeurs et non les clés. Ils seront presque toujours plus lents à moins que vous ne soyez nextrêmement petit.
Pacerier
Pourquoi pas $array[$key] === null?
Pacerier

Réponses:

237

isset()est plus rapide, mais ce n'est pas la même chose que array_key_exists().

array_key_exists()vérifie uniquement si la clé existe, même si la valeur est NULL.

Considérant que isset()retournera falsesi la clé existe et la valeur est NULL.

Richard Levasseur
la source
6
Avez-vous des ressources spécifiques affirmant que le jeu est plus rapide?
Francesco Pasa
@Francesco Pasa Pensez-y un peu. issetn'est pas une fonction de recherche de tableau, elle vérifie uniquement la présence d'une variable dans la table des symboles et n'itérera pas sur le tableau. array_key_existsd'autre part, itérera / recherchera les clés dans la première dimension du tableau spécifié.
Pluie le
@Rain Je suis sûr que array_key_exists()je ne vérifierai que si la clé est dans le tableau, ce qui signifie qu'elle ne fera pas de recherche puisqu'il s'agit d'une table de hachage.
Francesco Pasa le
@FrancescoPasa Eh bien, "rechercher les clés" est ce que dit la documentation PHP. À part cela, je ne peux pas dire si «chercher» pour eux signifie quelque chose de complètement différent de ce que cela signifie pour moi.
Pluie le
32

Si vous êtes intéressé par certains tests que j'ai effectués récemment:

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

Résumé:

| 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
la source
IMPORTANT: le timing de arrayKeyExists s'est avéré être très faux - il vérifiait la valeur et non la clé - suivez ce lien pour le timing révisé dans 7.1, ce qui est bien meilleur. (Ce serait également mieux dans les versions antérieures de php, si Populus refait ce test.)
ToolmakerSteve
19

Eh bien, la principale différence est que isset()ne reviendra pas truepour les clés de tableau qui correspondent à une valeur nulle, contrairement array_key_exists().

L'exécution d'un petit benchmark montre que isset()c'est plus rapide, mais ce n'est peut-être pas tout à fait exact.

CMS
la source
1
Pouvez-vous exécuter à nouveau le benchmark avec le plus correct "(isset ($ array [$ i]) || $ array [$ i] === null)"?
Tomalak
Oh, et pourriez-vous afficher une indication de la différence de performance des deux variantes? Merci!
Tomalak
1
@Tomalak, j'ai exécuté l'exemple que vous avez suggéré, et il indique que array_key_exists () est plus rapide que isset () avec le || opérateur. codepad.org/5qyvS93x
alex
1
Up from the dead ... mais j'ai aussi relancé le benchmark, et fait un tweak pour que la deuxième boucle for initialise son propre compteur et efface le tableau de résultats. Il montre que "isset || null" est plus rapide. codepad.org/Np6oPvgS
KyleWpppd
3
@Tomalak, isset($array[$i]) || $array[$i] === nulln'a pas de sens car il reviendra truepour chaque cas. Vous n'obtiendrez jamais faux isset($array[$i]) || $array[$i] === nullquelles que soient les entrées.
Pacerier
10

Je voulais ajouter mes 2 cents sur cette question, car il me manquait une solution intermédiaire.

Comme déjà dit isset(), évaluera la valeur de la clé de sorte qu'il retournera falsesi cette valeur est nullarray_key_exists()vérifier uniquement si la clé existe dans le tableau.


J'ai exécuté un benchmark simple en utilisant PHP 7, les résultats affichés sont le temps qu'il a fallu pour terminer l'itération:

$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

J'ai également ajouté les résultats de cette fonction personnalisée avec ce benchmark pour l'achèvement:

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

Comme vu et déjà dit, isset()c'est la méthode la plus rapide, mais elle peut renvoyer false si la valeur est null. Cela pourrait donner des résultats indésirables et on devrait généralement l'utiliser array_key_exists()si tel est le cas.

Cependant, il existe un moyen de sortir et qui utilise isset() || array_key_exists(). Ce code utilise généralement la fonction plus rapide isset()et si isset() renvoie false uniquement, utilisez array_key_exists()pour valider. Montré dans le tableau ci-dessus, c'est aussi rapide que d'appeler clairement isset().

Oui, c'est un peu plus de l'écrire et l'encapsuler dans une fonction est plus lent mais beaucoup plus facile. Si vous en avez besoin pour les performances, la vérification des données volumineuses, etc., écrivez-le complètement, sinon si c'est une utilisation une fois, cette surcharge très mineure en fonction array_key_isset()est négligeable.

Xorifelse
la source
7

Avec Php 7 donne la possibilité d'utiliser l' opérateur Null Coalescing .

L'opérateur de fusion nul (??) a été ajouté comme sucre syntaxique pour le cas courant de besoin d'utiliser un ternaire en conjonction avec isset (). Il renvoie son premier opérande s'il existe et n'est pas NULL; sinon, il renvoie son deuxième opérande.

Vous pouvez donc maintenant attribuer une valeur par défaut au cas où la valeur serait nulle ou si la clé n'existe pas:

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

il y a une différence avec php.net que vous lirez:

isset () ne renvoie pas TRUE pour les clés de tableau qui correspondent à une valeur NULL, contrairement à array_key_exists ().

Un test très informel se révèle array_key_exists()environ 2,5 fois plus lent queisset()

Scott Evernden
la source
3

La combinaison isset()et is_null()donner les meilleures performances par rapport à d' autres fonctions telles que : array_key_exists(), isset(), isset()+ array_key_exists(), is_null(), isset()+ is_null(), la seule question ici est la fonction non seulement return false si la clé n'existe pas, mais même la clé et exist a une valeur nulle.

Script de référence:

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

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

H Aßdøµ
la source
1

Quant à "plus rapide": essayez-le (mon argent est allumé array_key_exists(), mais je ne peux pas l'essayer pour le moment).

Quant à "plus clair dans l'intention": array_key_exists()

Tomalak
la source
3
isset () est en fait beaucoup plus rapide si vous ne vous souciez pas du comportement nul (voir randombenchmarks.com/?p=29 ).
Matt Kantor
0

De toute évidence, le deuxième exemple est plus clair dans l'intention, cela ne fait aucun doute. Pour comprendre ce que fait l'exemple n ° 1, vous devez vous familiariser avec les idiosyncraties d'initialisation des variables de PHP - et vous découvrirez ensuite qu'il fonctionne différemment pour les valeurs nulles, et ainsi de suite.

Quant à savoir lequel est le plus rapide - je n'ai pas l'intention de spéculer - exécutez non plus en boucle serrée quelques centaines de milliers de fois sur votre version PHP et vous le saurez :)

Mihai Limbășan
la source
-2

Votre code isset($array[$i]) || $array[$i] === null,, retournera true dans tous les cas, même si la clé n'existe pas (et produira un avis d'index non défini). Pour les meilleures performances, ce que vous voulezif (isset($array[$key]) || array_key_exists($key,$array)){doWhatIWant();}

Gator
la source
1
La seule fois $array[$i] === nullsera exécutée lorsque $ i existe dans le tableau et a la valeur NULL ..
Niclas Larsson