Auf leere Arrays prüfen: Anzahl vs leer

98

Diese Frage zu " Wie man erkennt, ob ein PHP-Array leer ist " ließ mich an diese Frage denken

Gibt es einen Grund, der countverwendet werden sollte, anstatt emptyfestzustellen, ob ein Array leer ist oder nicht?

Mein persönlicher Gedanke wäre, wenn die 2 für den Fall leerer Arrays gleichwertig sind, die Sie verwenden sollten, emptyda sie eine boolesche Antwort auf eine boolesche Frage geben. Aus der oben verlinkten Frage geht hervor, dass dies count($var) == 0die beliebte Methode ist. Für mich macht es zwar technisch korrekt, aber keinen Sinn. ZB F: $ var, bist du leer? A: 7 . Hmmm...

Gibt es einen Grund, den ich count == 0stattdessen verwenden sollte, oder nur eine Frage des persönlichen Geschmacks?

Wie von anderen in den Kommentaren für eine jetzt gelöschte Antwort hervorgehoben, counthat dies Auswirkungen auf die Leistung großer Arrays, da alle Elemente gezählt werden müssen, während emptysie angehalten werden können, sobald sie wissen, dass sie nicht leer sind. Wenn sie in diesem Fall die gleichen Ergebnisse liefern, aber countmöglicherweise ineffizient sind, warum sollten wir sie dann jemals verwenden count($var) == 0?

Dan McGrath
quelle
Ich gehe davon aus, dass Sie beabsichtigen, die Konversation ausschließlich auf Arrays zu beschränken, aber es kann erwähnenswert sein, dass sich das Spiel vollständig ändert, wenn Sie mit Objekten arbeiten (z. B. die Countable, Iterator usw. implementieren).
8
Ein leeres Array entspricht falsePHP - keine Notwendigkeit für empty()oder count().
Cobby
@Cobby Code bitte.
TheRealChx101
@ TheRealChx101 Wie in, machen Sie einfach: if (!$myArray) { echo "array is empty"; } sandbox.onlinephpfunctions.com/code/…
Cobby
Heutzutage wird die beliebte Option in der verknüpften Frage verwendet empty().
PhoneixS

Antworten:

97

Ich benutze im Allgemeinen empty. Ich bin mir nicht sicher, warum Leute count wirklich verwenden würden - Wenn das Array groß ist, dauert count länger / hat mehr Overhead. Wenn Sie nur wissen müssen, ob das Array leer ist oder nicht, verwenden Sie leer.

prodigitalson
quelle
4
Diese Funktionen unterscheiden sich tatsächlich, wenn das Array nicht leer ist.
Jacco
2
@Jacco: Ich bestreite das nicht. Aber wenn Sie es testen, ist es leer, ich sehe nicht, welche Relevanz das hat - es ist eine Frage mit einem booleschen Ergebnis, das die Funktion zurückgeben wird. In Bezug auf das, was in leer betrachtet wird, sehen Sie nicht, wie diese Kriterien die falsche Antwort liefern würden, es sei denn, die Variable, die Sie testen, ist kein Array, in welchem ​​Fall dies ein völlig anderes Problem ist.
Prodigitalson
23
@prodigitalson Ich würde sagen, dass count ist O(1), da PHP die Anzahl der Elemente intern speichert. Überprüfen Sie heraus diese Antwort stackoverflow.com/a/5835419/592454
elitalon
4
@eliton: aber trotzdem - auch wenn es keinen oder nur einen geringen Leistungsunterschied gibt, warum count verwenden, wenn Sie die Zählung nicht benötigen?
Wunderkinder
4
empty () verzeiht Fehler zu sehr. Ich habe gerade 2 Stunden damit verbracht, eine Unterklasse zu debuggen, die empty () für eine private Mitgliedsvariable ihrer Oberklasse getestet hat (der Umfang der Mitgliedsvariablen der Oberklasse SOLLTE geschützt sein, aber empty () hat keine Fehler zurückgegeben - das Ergebnis war einfach das, was sollte passiert ist, nicht passiert ist: Die Nichtexistenz der Mitgliedsvariablen in der Unterklasse wurde genauso behandelt, als ob diese Mitgliedsvariable, ein Array, leer wäre - dh als hätte sie keine Elemente). Dies ist problematisch und ein weiteres Beispiel dafür, dass PHP zu verzeihend ist.
Matthew Slyman
46

Ich war neugierig zu sehen, welches tatsächlich schneller ist, also habe ich ein einfaches Skript erstellt, um diese Funktionen zu bewerten.

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

Seitdem habe ich auch versucht, die Leistung bei Operationen zu überprüfen, die normalerweise mit count () / empty () verbunden sind.

Verwenden von 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

Verwenden von 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

Schlussfolgerungen, wenn Sie PHP verwenden:

  1. empty () ist in beiden Szenarien viel schneller als count (), mit einem leeren und aufgefüllten Array

  2. count () führt dasselbe mit einem vollständigen oder leeren Array aus.

  3. Das Ausführen einer einfachen IF oder nur einer Booleschen Operation ist dasselbe.

  4. IF / ELSE ist etwas effizienter als (? :). Wenn Sie nicht Milliarden von Iterationen mit Ausdrücken in der Mitte ausführen, ist dies völlig unbedeutend.

Schlussfolgerungen, wenn Sie HHVM verwenden:

  1. empty () ist ein kleines bisschen schneller als count (), aber unbedeutend.

    [Der Rest ist der gleiche wie in PHP]

Wenn Sie nur wissen möchten, ob das Array leer ist, verwenden Sie abschließend immer empty ().

Dies war nur ein merkwürdiger Test, der einfach durchgeführt wurde, ohne viele Dinge zu berücksichtigen. Es ist nur ein Proof of Concept und spiegelt möglicherweise nicht die Produktionsabläufe wider.

Satake
quelle
Vielen Dank für den Beispiel-Testcode. Ich habe ihn gerade verwendet und festgestellt, dass er if($x){schneller ist als if(empty($x)){(funktioniert nur, wenn Sie wissen, dass $xer deklariert wurde).
Redzarf
Ihr Testcode ist wirklich schlecht. Sie fügen viele zusätzliche Dinge hinzu, wie z. B. einen anonymen Funktionsaufruf. Wenn ich den Bare-Code entferne und nur ausführe (für einen Zyklus nach dem anderen), bekomme ich einen großen Unterschied. Und ich meine in diesem Fall umso schneller, wenn es keine gibt countund emptydie if-Anweisung aufruft. Dann kommt das emptyund dauert das count. Aber im Vergleich zu Ihrer im bloßen Fall ist die Leere zehnmal schneller! Einfacher Array-Test: 0.104662, leer: 0.177659, Anzahl: 1.175125 unter PHP 5.6, andernfalls liefert Ihr Code auch bei dieser Version das gleiche Ergebnis wie bei Ihrem erwähnten. Es sind nur falsche Ergebnisse.
golddragon007
16

Ich denke, es ist nur eine persönliche Präferenz. Einige Leute sagen vielleicht, es emptysei schneller (z. B. http://jamessocol.com/projects/count_vs_empty.php ), während andere sagen könnten, es countsei besser, da es ursprünglich für Arrays gemacht wurde.emptyist allgemeiner und kann auf andere Typen angewendet werden.

php.net gibt jedoch die folgende Warnung aus count:

count () kann 0 für eine Variable zurückgeben, die nicht gesetzt ist, aber es kann auch 0 für eine Variable zurückgeben, die mit einem leeren Array initialisiert wurde. Verwenden Sie isset (), um zu testen, ob eine Variable festgelegt ist.

Mit anderen Worten, wenn die Variable nicht festgelegt ist, erhalten Sie von PHP eine Benachrichtigung, dass sie undefiniert ist. Daher ist es vor der Verwendung countvorzuziehen, die Variable mit zu überprüfen isset. Dies ist bei nicht erforderlich empty.

Laurent le Beau-Martin
quelle
3
Es ist interessant, dass ein Argument dafür countist, dass es ursprünglich für Arrays gemacht wurde ... Objekte können jedoch implementiert werden Countable, und Sie können Skalarwerte an übergeben count()und ein gültiges Ergebnis erhalten.
1
count () kann zurückgeben 0 für eine Variable, die nicht gesetzt ist, aber es kann auch ... . Offizielle Dokumentation mit Modalverben, um seine Unsicherheit auszudrücken: p
nawfal
Nur ein Kommentar zum isset()Punkt. Wenn Sie sich Sorgen über Hinweise in PHP machen, sollten Sie Ihr Array bereits deklariert haben. Wenn Sie PHP Ihr Array dynamisch deklarieren lassen, erhalten Sie auch an dieser Stelle eine Benachrichtigung. Ich denke, der eigentliche Punkt der Warnung auf php.net ist, dass Sie nicht verwenden sollten, countum festzustellen, ob ein Array deklariert wurde oder nicht, da es das gleiche Ergebnis liefert wie ein leeres Array.
Noah Duncan
12

Gibt es einen Grund, warum count anstelle von leer verwendet werden sollte, um festzustellen, ob ein Array leer ist oder nicht?

Wenn Sie etwas für ein nicht leeres Array tun müssen, wissen Sie, wie groß es ist:

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

Aber ich würde nicht empfehlen, count zu verwenden, es sei denn, Sie sind sich zu 100% sicher, dass das, was Sie zählen, ein Array ist. In letzter Zeit habe ich Code debuggt, bei dem eine Fehlerfunktion FALSEanstelle eines leeren Arrays zurückgegeben wurde, und ich habe Folgendes entdeckt:

var_dump(count(FALSE));

Ausgabe:

int 1

Seitdem verwende ich emptyoder if(array() === $array)um sicherzugehen, dass ich ein Array habe , das leer ist.

Dev-Null-Bewohner
quelle
6

count()scheint mit Array-ähnlichen Schnittstellen, die implementiert werden, besser zu funktionieren ArrayAccess/Countable. empty()Gibt true für diese Art von Objekten zurück, auch wenn sie keine Elemente enthalten. In der Regel implementieren diese Klassen die CountableSchnittstelle. Wenn die Frage lautet: "Enthält diese Sammlung Elemente?" Ohne eine Annahme über die Implementierung zu machen, count()ist dies eine bessere Option.

Ryan
quelle
Meinen Sie " emptygibt für diese Art von Objekten false zurück, auch wenn sie keine Elemente enthalten"?
Alexw
Ja. Es gibt keine Schnittstelle, über die eine Klasse definieren kann, ob sie "leer" ist oder nicht. Und es würde nicht wirklich Sinn machen, wenn es einen gäbe.
Ryan
1 Mit counteiner flexibleren und erweiterbare Lösung wäre, wenn immer es sinnvoll für Ihren Code macht eine „gemeinsame“ Art und Weise eine Sammlung umgesetzt zu akzeptieren ... IMO das könnte die nur die relevanten Kriterien für die Definition, wenn Sie verwenden countoder andere Weise ...
ClemC
Der große Nachteil von count()ab 7.2 ist, dass keine leeren Variablen mehr aufgenommen werden können.
Ryan
5

Alternativ können Sie die Variable als Booleschen Wert (implizit oder explizit) umwandeln:

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

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

Diese Methode generiert eine, E_NOTICEwenn die Variable nicht definiert ist, ähnlich wiecount() .

Weitere Informationen finden Sie auf der Seite PHP-Handbuch zu Typvergleichen .


quelle
1
Dies ist der beste Weg, dies zu überprüfen. Verwenden empty()Sie es nur, wenn Sie explizit versuchen, das Auslösen eines E_NOTICE zu vermeiden (was im Allgemeinen eine schlechte Idee ist, IMO). Die offensichtliche Verwendung von leer führt zu fehlerhaftem Code.
Cobby
3

Meine persönliche Präferenz ist eher das Codieren von Eleganz (in Bezug auf meinen spezifischen Anwendungsfall). Ich stimme Dan McG insofern zu, als count () nicht mit dem richtigen Datentyp (in diesem Fall boolesch) für den fraglichen Test antwortet und den Entwickler dazu zwingt, mehr Code zu schreiben, um eine 'if'-Anweisung zu füllen.

Ob dies einen signifikanten Einfluss auf die Leistung hat, ist nur für extrem große Arrays umstritten (für die Sie in den meisten Setups wahrscheinlich ohnehin nicht genügend Speicherzuweisung haben).

Insbesondere wenn es um das $ _POST-Array von PHP geht, erscheint es meiner Meinung nach viel "logischer", zu schreiben / zu sehen:

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

Hoffe, dies könnte jemandem helfen, obwohl es bereits beantwortet wurde (und was diskutiert wurde). In meinem eigenen Szenario weiß ich, dass alle meine Arrays 7 Elemente haben (Überprüfungen wurden früher in meinem Code durchgeführt) und ich führe eine ausarray_diff das natürlich ein Array von Null zurückgibt, wenn es gleich ist.

Ich hatte 34 Sekunden für countund 17 Sekunden fürempty . Beide geben mir die gleichen Berechnungen, so dass mein Code immer noch in Ordnung ist.

Sie können jedoch auch das ==oder ===wie in PHP ausprobieren - Überprüfen Sie, ob zwei Arrays gleich sind . Das Beste, was ich sagen würde, ist versuchen countgegen emptyvs == empty array, dann sehen Sie, welche Ihre eigenen besten Perfs gibt. In meinem Fall countwar der langsamste, also benutze ich emptyjetzt ... werde als serializenächstes prüfen

xchiltonx
quelle
2

Es gibt keinen guten Grund zu bevorzugen count($myArray) == 0über empty($myArray). Sie haben identische Semantik. Einige finden vielleicht eine besser lesbar als die andere. Eine Leistung ist möglicherweise geringfügig besser als die andere, aber bei der überwiegenden Mehrheit der PHP-Anwendungen ist dies wahrscheinlich kein wesentlicher Faktor. Für alle praktischen Zwecke ist die Wahl Geschmackssache.

Asaph
quelle
1
Was ist mit der "Performance" -Sache? Die Erklärung von "praktischen Zwecken" führt zu schlechten Gewohnheiten. Verwenden countSie diese Option, emptywenn Sie zählen müssen. Verwenden Sie diese Option, wenn Sie überprüfen müssen, ob die Sammlung leer ist. Natürlich gibt es Randfälle wie Zeichenfolgen oder Nullen, aber der Programmierer muss über seinen Code nachdenken. Sie können nicht zustimmen, Sie dürfen.
Namek
Manchmal funktioniert die Zählung mit count ($ myArray) nicht, wenn $ myArray ein Booleen wie ein Wert FALSE ist (getestet auf PHP5.3).
Mimouni
1

Manchmal ist es ein Muss, leer zu verwenden. Zum Beispiel dieser 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);

Wenn Sie diesen Code folgendermaßen ausführen: http://phpfiddle.org/main/code/g9x-uwi

Sie erhalten diese Ausgabe:

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

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

Also, wenn Sie count die leere Glob-Ausgabe haben, erhalten Sie eine falsche Ausgabe. Sie sollten auf Leere prüfen.

Aus der Glob- Dokumentation:

Gibt ein Array zurück, das die übereinstimmenden Dateien / Verzeichnisse enthält, ein leeres Array, wenn keine Datei übereinstimmt, oder FALSE bei einem Fehler.
Hinweis: Auf einigen Systemen kann nicht zwischen leerer Übereinstimmung und einem Fehler unterschieden werden.

Überprüfen Sie auch diese Frage: Warum zählen (falsch) 1 zurück?

trante
quelle
1

Da eine als negativ analysierte Variable int(1)mit zurückkehren würdecount()

Ich teste lieber ($array === [] || !$array)auf ein leeres Array.

Ja, wir sollten ein leeres Array erwarten, aber wir sollten keine gute Implementierung von Funktionen ohne erzwungene Rückgabetypen erwarten.

Beispiele mit count()

var_dump(count(0));
> int(1)
var_dump(count(false));
> int(1)
Sdlion
quelle
0

Ich habe meine Gedanken neu gemacht, Leute, danke.

Ok, es gibt keinen Unterschied zwischen der Verwendung von emptyund count. Technisch countsollte für Arrays verwendet werden und emptykönnte sowohl für Arrays als auch für Strings verwendet werden. In den meisten Fällen sind sie also austauschbar. Wenn Sie die PHP-Dokumente sehen, sehen Sie die Vorschlagsliste, countob Sie sich gerade befinden emptyund umgekehrt.

Sarfraz
quelle