Vérification des tableaux vides: nombre vs vide

98

Cette question sur ' Comment savoir si un tableau PHP est vide ' m'a fait réfléchir à cette question

Y a-t-il une raison countà utiliser au lieu de emptydéterminer si un tableau est vide ou non?

Ma pensée personnelle serait si les 2 sont équivalents pour le cas des tableaux vides que vous devriez utiliser emptycar cela donne une réponse booléenne à une question booléenne. D'après la question liée ci-dessus, il semble que ce count($var) == 0soit la méthode populaire. Pour moi, bien que techniquement correct, cela n'a aucun sens. Ex : Q: $ var, êtes-vous vide? R: 7 . Hmmm ...

Y a-t-il une raison pour laquelle je devrais utiliser à la count == 0place ou juste une question de goût personnel?

Comme indiqué par d'autres dans les commentaires pour une réponse maintenant supprimée, countaura des impacts sur les performances pour les grands tableaux car il devra compter tous les éléments, alors qu'il emptypeut s'arrêter dès qu'il sait qu'il n'est pas vide. Donc, s'ils donnent les mêmes résultats dans ce cas, mais countsont potentiellement inefficaces, pourquoi utiliserions-nous jamais count($var) == 0?

Dan McGrath
la source
Je suppose que votre intention est de limiter la conversation exclusivement aux tableaux, mais il peut être intéressant de noter que le jeu change complètement si vous travaillez avec des objets (par exemple, qui implémentent Countable, Iterator, etc.).
9
Un tableau vide est égal à falseen PHP - pas besoin de empty()ou count().
Cobby
@Cobby Code s'il vous plaît.
TheRealChx101
@ TheRealChx101 Comme dans, il suffit de faire: if (!$myArray) { echo "array is empty"; } sandbox.onlinephpfunctions.com/code/…
Cobby
De nos jours, l'option populaire dans la question liée utilise empty().
PhoneixS

Réponses:

97

J'utilise généralement empty. Je ne sais pas pourquoi les gens utiliseraient vraiment count - Si le tableau est grand, alors count prend plus de temps / a plus de frais généraux. Si vous avez simplement besoin de savoir si le tableau est vide ou non, utilisez vide.

prodigitalson
la source
4
Ces fonctions diffèrent en effet lorsque le tableau n'est pas vide.
Jacco
2
@Jacco: Je ne conteste pas cela. Mais si vous le testez, il est vide, je ne vois pas quelle pertinence cela a - c'est une question avec un résultat booléen qui est ce que la fonction retournera. En ce qui concerne ce qui est considéré comme vide, ne voyez pas comment ces critères produiraient la mauvaise réponse à moins que la variable de votre test ne soit pas un tableau dans ce cas, c'est un problème entièrement différent.
prodigitals le
23
@prodigitalson Je dirais que count est O(1), puisque PHP stocke le nombre d'éléments en interne. Découvrez cette réponse stackoverflow.com/a/5835419/592454
elitalon
4
@eliton: mais quand même - même s'il n'y a pas ou peu de différence de performances, pourquoi utiliser count si vous n'avez pas besoin du compte?
prodigitals
4
empty () pardonne trop les erreurs. Je viens de passer 2 heures à déboguer une sous-classe qui a testé empty () sur une variable de membre privé de sa superclasse (la portée de la variable membre de la superclasse DEVRAIT être protégée, mais empty () n'a renvoyé aucune erreur - le résultat était simplement que quelque chose qui devrait est arrivé, ne s'est pas produit: la non-existence de la variable membre dans la sous-classe a été traitée exactement de la même manière que si cette variable membre, un tableau, était vide - c'est-à-dire comme si elle ne contenait aucun élément). C'est problématique, et c'est un autre exemple de PHP trop indulgent.
Matthew Slyman
47

J'étais curieux de voir lequel était en fait le plus rapide, alors j'ai créé un script simple pour comparer ces fonctions.

<?php

function benchmark($name, $iterations, $action){
    $time=microtime(true);
    for($i=0;$i<=$iterations;++$i){
        $action();
    }
    echo $name . ' ' . round(microtime(true)-$time, 6) . "\n";
}

$iterations = 1000000;
$x = array();
$y = range(0, 10000000);
$actions = array(
    "Empty empty()" => function() use($x){
        empty($x);
    },
    "Empty count()" => function() use($x){
        count($x);
    },
    "Full empty()" => function() use($y){
        empty($y);
    },
    "Full count()" => function() use($y){
        count($y);
    },
    ############
    "IF empty empty()" => function() use($x){
        if(empty($x)){ $t=1; }
    },
    "IF empty count()" => function() use($x){
        if(count($x)){ $t=1; }
    },
    "IF full empty()" => function() use($y){
        if(empty($y)){ $t=1; }
    },
    "IF full count()" => function() use($y){
        if(count($y)){ $t=1; }
    },
    ############
    "OR empty empty()" => function() use($x){
        empty($x) OR $t=1;
    },
    "OR empty count()" => function() use($x){
        count($x) OR $t=1;
    },
    "OR full empty()" => function() use($y){
        empty($y) OR $t=1;
    },
    "OR full count()" => function() use($y){
        count($y) OR $t=1;
    },
    ############
    "IF/ELSE empty empty()" => function() use($x){
        if(empty($x)){ $t=1; } else { $t=2; }
    },
    "IF/ELSE empty count()" => function() use($x){
        if(count($x)){ $t=1; } else { $t=2; }
    },
    "IF/ELSE full empty()" => function() use($y){
        if(empty($y)){ $t=1; } else { $t=2; }
    },
    "IF/ELSE full count()" => function() use($y){
        if(count($y)){ $t=1; } else { $t=2; }
    },
    ############
    "( ? : ) empty empty()" => function() use($x){
        $t = (empty($x) ? 1 : 2);
    },
    "( ? : ) empty count()" => function() use($x){
        $t = (count($x) ? 1 : 2);
    },
    "( ? : ) full empty()" => function() use($y){
        $t = (empty($y) ? 1 : 2);
    },
    "( ? : ) full count()" => function() use($y){
        $t = (count($y) ? 1 : 2);
    }
);

foreach($actions as $name => $action){
    benchmark($name, $iterations, $action);
}
//END

Depuis que je le faisais, j'ai également essayé de vérifier les performances en effectuant des opérations qui seraient normalement associées à count () / empty ()

En utilisant PHP 5.4.39:

Empty empty() 0.118691
Empty count() 0.218974
Full empty() 0.133747
Full count() 0.216424
IF empty empty() 0.166474
IF empty count() 0.235922
IF full empty() 0.120642
IF full count() 0.248273
OR empty empty() 0.123875
OR empty count() 0.258665
OR full empty() 0.157839
OR full count() 0.224869
IF/ELSE empty empty() 0.167004
IF/ELSE empty count() 0.263351
IF/ELSE full empty() 0.145794
IF/ELSE full count() 0.248425
( ? : ) empty empty() 0.169487
( ? : ) empty count() 0.265701
( ? : ) full empty() 0.149847
( ? : ) full count() 0.252891

Utilisation de HipHop VM 3.6.1 (dbg)

Empty empty() 0.210652
Empty count() 0.212123
Full empty() 0.206016
Full count() 0.204722
IF empty empty() 0.227852
IF empty count() 0.219821
IF full empty() 0.220823
IF full count() 0.221397
OR empty empty() 0.218813
OR empty count() 0.220105
OR full empty() 0.229118
OR full count() 0.221787
IF/ELSE empty empty() 0.221499
IF/ELSE empty count() 0.221274
IF/ELSE full empty() 0.221879
IF/ELSE full count() 0.228737
( ? : ) empty empty() 0.224143
( ? : ) empty count() 0.222459
( ? : ) full empty() 0.221606
( ? : ) full count() 0.231288

Conclusions si vous utilisez PHP:

  1. empty () est beaucoup plus rapide que count () dans les deux scénarios, avec un tableau vide et rempli

  2. count () effectue la même chose avec un tableau plein ou vide.

  3. Faire un simple IF ou simplement une opération booléenne est la même chose.

  4. IF / ELSE est très légèrement plus efficace que (?:). À moins que vous ne fassiez des milliards d'itérations avec des expressions au milieu, c'est complètement insignifiant.

Conclusions si vous utilisez HHVM:

  1. empty () est un tout petit peu plus rapide que count () mais de manière insignifiante.

    [Le reste est le même qu'en PHP]

En conclusion, si vous avez juste besoin de savoir si le tableau est vide, utilisez toujours empty ();

Ce n'était qu'un curieux test effectué simplement sans prendre en compte beaucoup de choses. Il s'agit simplement d'une preuve de concept et peut ne pas refléter les opérations de production.

Satake
la source
Merci pour l'exemple de code de test .... Je viens de l'utiliser et j'ai trouvé que if($x){c'est plus rapide que if(empty($x)){(ne fonctionne que si vous savez que cela $xa été déclaré).
Redzarf
Votre code de test est vraiment mauvais. Vous ajoutez beaucoup de choses supplémentaires, comme un appel de fonction anonyme. Si je supprime et que j'exécute simplement le code nu (pour un cycle après l'autre), j'obtiens une énorme différence. Et je veux dire dans ce cas le plus rapide s'il n'y a pas countet emptyappelle dans l'instruction if. Ensuite, il vient le emptyet dure le count. Mais comparé au vôtre en cas nu, le vide est dix fois plus rapide! Test de tableau simple: 0.104662, vide: 0.177659, compte: 1.175125 sur PHP 5.6 sinon votre code donne le même résultat sur cette version aussi comme celui que vous avez mentionné. Ce sont juste de faux résultats.
golddragon007
16

Je pense que ce n'est qu'une préférence personnelle. Certains pourraient dire que emptyc'est plus rapide (par exemple http://jamessocol.com/projects/count_vs_empty.php ) tandis que d'autres pourraient dire que countc'est mieux car il a été conçu à l'origine pour les tableaux. emptyest plus général et peut être appliqué à d'autres types.

php.net donne cependant l'avertissement suivant count:

count () peut renvoyer 0 pour une variable qui n'est pas définie, mais il peut également renvoyer 0 pour une variable qui a été initialisée avec un tableau vide. Utilisez isset () pour tester si une variable est définie.

En d'autres termes, si la variable n'est pas définie, vous recevrez un avis de PHP indiquant qu'elle n'est pas définie. Par conséquent, avant d'utiliser count, il serait préférable de vérifier la variable avec isset. Ce n'est pas nécessaire avec empty.

Laurent le Beau-Martin
la source
3
Il est intéressant de noter qu'un argument en faveur de countest qu'il a été initialement conçu pour les tableaux ... mais les objets peuvent être implémentés Countable, et vous pouvez passer des valeurs scalaires à count()et obtenir un résultat valide.
1
count () peut retourner 0 pour une variable non définie, mais elle peut aussi ... . Documentation officielle utilisant des verbes modaux pour exprimer son incertitude: p
nawfal
Juste un commentaire sur ce isset()point. Si vous vous inquiétez des avis en PHP, vous devriez déjà avoir déclaré votre tableau. Si vous laissez PHP déclarer dynamiquement votre tableau, vous recevrez également une notification à ce stade. Je pense que le vrai point de l'avertissement sur php.net est que vous ne devriez pas utiliser countpour déterminer si un tableau a été déclaré ou non car il donne le même résultat qu'un tableau vide.
Noah Duncan
12

Y a-t-il une raison pour laquelle count devrait être utilisé au lieu de vide pour déterminer si un tableau est vide ou non?

Il y a, lorsque vous devez faire quelque chose sur un tableau non vide en sachant sa taille:

if( 0 < ( $cnt = count($array) ) )
{
 echo "Your array size is: $cnt";
}
else
 echo "Too bad, your array is empty :(";

Mais je ne recommanderais pas d'utiliser count, à moins que vous ne soyez sûr à 100% que ce que vous comptez est un tableau. Dernièrement, j'ai débogué du code, où la fonction d'erreur retournait FALSEau lieu d'un tableau vide, et ce que j'ai découvert était:

var_dump(count(FALSE));

production:

int 1

Donc, depuis lors, j'utilise emptyou if(array() === $array)pour être sûr que j'ai un tableau vide.

dev-null-dweller
la source
6

count()semble mieux fonctionner avec les interfaces de type tableau qui implémentent ArrayAccess/Countable. empty()renvoie true pour ces types d'objets même s'ils n'ont aucun élément. En règle générale, ces classes implémenteront l' Countableinterface, donc si la question est "Cette collection contient-elle des éléments?" sans faire d'hypothèse sur la mise en œuvre, alors count()est une meilleure option.

Ryan
la source
Voulez-vous dire " emptyrenvoie faux pour ces types d'objets même s'ils n'ont aucun élément"?
alexw
Oui. Il n'y a pas d'interface pour permettre à une classe de définir si elle est "vide" ou non. Et cela n'aurait pas vraiment de sens qu'il y en ait un.
Ryan
+1 Utiliser countserait une solution plus flexible et extensible si jamais il était logique que votre code accepte une collection implémentée de manière "commune" ... IMO qui pourrait être le seul critère pertinent pour définir si vous utilisez countou d'autres moyens ...
ClemC
L'énorme inconvénient de la version count()7.2 est qu'il ne peut plus accepter de variables vides.
Ryan
5

Vous pouvez également convertir la variable en booléen (implicitement ou explicitement):

if( $value )
{
  // array is not empty
}

if( (bool) $value )
{
  // array is still not empty
}

Cette méthode génère un E_NOTICEsi la variable n'est pas définie, de la même manière que count().

Pour plus d'informations, consultez la page du manuel PHP sur les comparaisons de types .


la source
1
C'est la meilleure façon de vérifier, à n'utiliser que empty()si vous essayez explicitement d'éviter de déclencher un E_NOTICE (ce qui est généralement une mauvaise idée, IMO). L'utilisation flagrante de empty conduira à un code bogué.
Cobby
3

Ma préférence personnelle est plus pour le codage de l'élégance (par rapport à mon cas d'utilisation spécifique). Je suis d'accord avec Dan McG dans la mesure où count () ne répond pas avec le type de données correct (dans ce cas booléen) pour le test en question, ce qui oblige le développeur à écrire plus de code pour remplir une instruction `` if ''.

Que cela ait un impact significatif sur les performances n'est discutable que pour les baies extrêmement grandes (pour lesquelles vous n'aurez probablement pas assez de mémoire pour de toute façon dans la plupart des configurations).

Particulièrement en ce qui concerne le tableau $ _POST de PHP, il semble beaucoup plus "logique" à mon avis d'écrire / voir:

if ( !empty ( $_POST ) ) {
    // deal with postdata
}
Simonhamp
la source
3

J'espère que cela pourrait aider quelqu'un même s'il a déjà été répondu (et débattu de quoi). Dans mon propre scénario, je sais que tous mes tableaux ont tous 7 éléments (les vérifications ont été effectuées plus tôt dans mon code) et j'effectue un array_diffqui, bien sûr, renvoie un tableau de zéro lorsqu'il est égal.

J'ai eu 34 secondes pour countet 17 secondes pour empty. Les deux me donnent les mêmes calculs donc mon code est toujours correct.

Cependant, vous pouvez également essayer le ==ou ===comme en PHP - Vérifiez si deux tableaux sont égaux . Le mieux que je dirais est d'essayer countvs emptyvs == empty array, puis de voir ce qui vous donne les meilleures performances. Dans mon cas, countc'était le plus lent, donc j'utilise emptymaintenant ... vérifiera serializeensuite

xchiltonx
la source
2

Il n'y a pas de raison forte à préférer count($myArray) == 0plus empty($myArray). Ils ont une sémantique identique. Certains pourraient trouver l'un plus lisible que l'autre. L'un peut fonctionner légèrement mieux que l'autre, mais il est peu probable que ce soit un facteur significatif dans la grande majorité des applications php. À toutes fins pratiques, le choix est une question de goût.

Asaph
la source
1
Qu'en est-il de la "performance"? Utiliser l'explication des «fins pratiques» conduit à de mauvaises habitudes. À utiliser countlorsque vous avez besoin de compter, à utiliser emptylorsque vous devez vérifier si la collection est vide. Bien sûr, il existe des cas extrêmes comme des chaînes ou des valeurs nulles, mais le programmeur doit réfléchir à son code. Vous pouvez être en désaccord, vous êtes autorisé à le faire.
Namek
parfois, avec count ($ myArray) si $ myArray est un booleen comme une valeur FALSE, le count ne fonctionne pas (testé sur php5.3).
Mimouni
1

Parfois, l'utilisation de vide est un must. Par exemple ce code:

$myarray = array();

echo "myarray:"; var_dump($myarray); echo "<br>";
echo "case1 count: ".count($myarray)."<br>";
echo "case1 empty: ".empty($myarray)."<br>";

$glob = glob('sdfsdfdsf.txt');

echo "glob:"; var_dump($glob); echo "<br>";
echo "case2 count: ".count($glob)."<br>";
echo "case2 empty: ".empty($glob);

Si vous exécutez ce code comme ceci: http://phpfiddle.org/main/code/g9x-uwi

Vous obtenez cette sortie:

myarray:array(0) { } 
case1 count: 0
case1 empty: 1

glob:bool(false) 
case2 count: 1
case2 empty: 1

Donc, si vous countla sortie glob vide, vous obtenez une mauvaise sortie. Vous devriez vérifier le vide.

De la documentation de glob :

Renvoie un tableau contenant les fichiers / répertoires correspondants, un tableau vide si aucun fichier ne correspond ou FALSE en cas d'erreur.
Remarque: sur certains systèmes, il est impossible de faire la distinction entre une correspondance vide et une erreur.

Vérifiez également cette question: Pourquoi compter (faux) retour 1?

trante
la source
1

Puisqu'une variable analysée comme négative reviendrait int(1)aveccount()

Je préfère ($array === [] || !$array)tester un tableau vide.

Oui, nous devrions nous attendre à un tableau vide, mais nous ne devrions pas nous attendre à une bonne implémentation sur des fonctions sans types de retour forcés.

Exemples avec count()

var_dump(count(0));
> int(1)
var_dump(count(false));
> int(1)
Sdlion
la source
0

J'ai refait mon esprit les gars, merci.

Ok, il n'y a aucune différence entre l'utilisation de emptyet count. Techniquement, countdevrait être utilisé pour les tableaux et emptypourrait être utilisé pour les tableaux ainsi que les chaînes. Donc, dans la plupart des cas, ils sont interchangeables et si vous voyez la documentation php, vous verrez la liste des suggestions countsi vous êtes à emptyet vice versa.

Sarfraz
la source