Controllo di array vuoti: count vs empty


98

Questa domanda su ' Come sapere se un array PHP è vuoto ' mi ha fatto pensare a questa domanda

C'è una ragione che countdovrebbe essere usata al posto di emptyquando si determina se un array è vuoto o no?

Il mio pensiero personale sarebbe se i 2 fossero equivalenti per il caso di array vuoti che dovresti usare emptyperché fornisce una risposta booleana a una domanda booleana. Dalla domanda collegata sopra, sembra che count($var) == 0sia il metodo popolare. Per me, anche se tecnicamente corretto, non ha senso. Ad esempio Q: $ var, sei vuoto? A: 7 . Hmmm ...

C'è un motivo per cui dovrei usare count == 0invece o solo una questione di gusto personale?

Come sottolineato da altri nei commenti per una risposta ora eliminata, countavrà un impatto sulle prestazioni per array di grandi dimensioni perché dovrà contare tutti gli elementi, mentre emptypuò fermarsi non appena sa di non essere vuoto. Quindi, se danno gli stessi risultati in questo caso, ma countsono potenzialmente inefficienti, perché dovremmo mai usarli count($var) == 0?


Presumo che la tua intenzione sia limitare la conversazione esclusivamente agli array, ma potrebbe valere la pena notare che il gioco cambia completamente se lavori con oggetti (ad esempio, che implementano Countable, Iterator, ecc.).

8
Un array vuoto è uguale a falsein PHP - non è necessario empty()o count().
Cobby

@Cobby Code per favore.
TheRealChx101

@ TheRealChx101 Come in, basta fare: if (!$myArray) { echo "array is empty"; } sandbox.onlinephpfunctions.com/code/...
Cobby

Al giorno d'oggi, viene utilizzata l'opzione popolare nella domanda collegata empty().
PhoneixS

Risposte:


97

Io generalmente uso empty. Non sono sicuro del motivo per cui le persone userebbero davvero count - Se l'array è grande, count richiede più tempo / ha più overhead. Se hai semplicemente bisogno di sapere se l'array è vuoto o meno, usa empty.


4
Queste funzioni infatti differiscono quando l'array non è vuoto.
Jacco

2
@ Jacco: Non lo metto in dubbio. Ma se lo stai testando è vuoto, non vedo quale rilevanza abbia - è una domanda con un risultato booleano che è ciò che la funzione restituirà. Riguardo a ciò che è considerato vuoto, non vedo come quei criteri potrebbero produrre la risposta sbagliata a meno che la variabile del tuo test non sia un array, nel qual caso questo è un problema completamente diverso.
Prodigitalil

23
@prodigitalson direi che il conteggio è O(1), poiché PHP memorizza il numero di elementi internamente. Dai un'occhiata a questo risposta stackoverflow.com/a/5835419/592454
elitalon

4
@eliton: ma comunque - anche se c'è poca o nessuna differenza nelle prestazioni, perché usare count se non hai bisogno del conteggio?
prodigitali

4
empty () perdona troppo gli errori. Ho appena trascorso 2 ore a eseguire il debug di una sottoclasse che ha testato empty () su una variabile membro privata della sua superclasse (l'ambito della variabile membro della superclasse DOVREBBE essere stato protetto, ma empty () non ha restituito errori - il risultato è stato semplicemente che qualcosa che dovrebbe è successo, non è accaduto: la non esistenza della variabile membro nella sottoclasse è stata trattata esattamente allo stesso modo come se questa variabile membro, un array, fosse vuota - cioè, come se non avesse elementi). Questo è problematico e un altro esempio di PHP troppo indulgente.
Matthew Slyman

46

Ero curioso di vedere quale fosse effettivamente più veloce, quindi ho creato un semplice script per confrontare queste funzioni.

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

Visto che lo stavo facendo ho anche provato a controllare le prestazioni facendo operazioni che normalmente sarebbero associate a count () / empty ()

Utilizzando 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

Utilizzo di 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

Conclusioni se stai usando PHP:

  1. empty () è molto più veloce di count () in entrambi gli scenari, con un array vuoto e popolato

  2. count () esegue lo stesso con un array pieno o vuoto.

  3. L'esecuzione di un semplice IF o solo di un'operazione booleana è la stessa cosa.

  4. IF / ELSE è leggermente più efficiente di (? :). A meno che tu non stia facendo miliardi di iterazioni con espressioni nel mezzo, è completamente insignificante.

Conclusioni se stai usando HHVM:

  1. empty () è un po 'più veloce di count () ma in modo insignificante.

    [Il resto è lo stesso di PHP]

In conclusione, se hai solo bisogno di sapere se l'array è vuoto usa sempre empty ();

Questo era solo un curioso test fatto semplicemente senza tenere in considerazione molte cose. È solo una prova di concetto e potrebbe non riflettere le operazioni in produzione.


Grazie per il codice di prova di esempio .... L'ho appena usato e ho scoperto che if($x){è più veloce di if(empty($x)){(funziona solo se sai che $xè stato dichiarato).
Redzarf

Il tuo codice di prova è davvero pessimo. Stai aggiungendo molte cose aggiuntive, come una chiamata di funzione anonima. Se rimuovo ed eseguo il codice nudo (per cicli uno dopo l'altro), ottengo un'enorme differenza. E intendo in quel caso il più veloce se non ci sono counte emptychiama l'istruzione if. Poi arriva il emptye dura il count. Ma rispetto al tuo in caso nudo, il vuoto è dieci volte più veloce! Test array semplice: 0.104662, vuoto: 0.177659, conteggio: 1.175125 su PHP 5.6 altrimenti il ​​tuo codice dà lo stesso risultato anche su questa versione come quella menzionata. Sono solo risultati falsi.
golddragon007

16

Penso che sia solo una preferenza personale. Alcune persone potrebbero dire che emptyè più veloce (ad es. Http://jamessocol.com/projects/count_vs_empty.php ) mentre altri potrebbero dire che countè migliore poiché è stato originariamente creato per gli array. emptyè più generale e può essere applicato ad altri tipi.

Tuttavia, php.net fornisce il seguente avviso count:

count () può restituire 0 per una variabile che non è impostata, ma può anche restituire 0 per una variabile che è stata inizializzata con un array vuoto. Usa isset () per verificare se una variabile è impostata.

In altre parole, se la variabile non è impostata, riceverai un avviso da PHP che dice che è indefinita. Pertanto, prima di utilizzare count, sarebbe preferibile controllare la variabile con isset. Questo non è necessario con empty.


3
È interessante notare che un argomento a favore countè che è stato originariamente creato per gli array ... tuttavia gli oggetti possono essere implementati Countablee puoi passare valori scalari count()e ottenere un risultato valido.

1
count () può restituire 0 per una variabile che non è impostata, ma può anche ... . Documentazione ufficiale che utilizza i verbi modali per esprimere la propria incertezza: p
nawfal

Solo un commento sul isset()punto. Se sei preoccupato per gli avvisi in PHP dovresti aver già dichiarato il tuo array. Se lasci che PHP dichiari dinamicamente il tuo array, riceverai anche un avviso a quel punto. Penso che il vero punto dell'avvertimento su php.net sia che non dovresti usare countper determinare se un array è stato dichiarato o meno in quanto restituisce lo stesso risultato di un array vuoto.
Noah Duncan

12

C'è una ragione per cui count dovrebbe essere usato invece di vuoto quando si determina se un array è vuoto o no?

C'è, quando devi fare qualcosa su un array non vuoto sapendo la sua dimensione:

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

Ma non consiglierei di usare count, a meno che tu non sia sicuro al 100% che quello che stai contando è un array. Ultimamente ho eseguito il debug del codice, dove la funzione di errore stava restituendo FALSEinvece di un array vuoto, e quello che ho scoperto è stato:

var_dump(count(FALSE));

produzione:

int 1

Quindi da allora sto usando emptyo if(array() === $array)per essere sicuro di avere un array vuoto.


6

count()sembra funzionare meglio con interfacce tipo array che implementano ArrayAccess/Countable. empty()restituisce true per questi tipi di oggetti anche se non hanno elementi. In genere queste classi implementeranno l' Countableinterfaccia, quindi se la domanda è "Questa raccolta contiene elementi?" senza fare un'ipotesi sull'implementazione, allora count()è un'opzione migliore.


Intendi " emptyrestituisce false per questo tipo di oggetti anche se non hanno elementi"?
alexw

Sì. Non esiste un'interfaccia che consenta a una classe di definire se è "vuota" o meno. E non avrebbe davvero senso che ce ne fosse uno.
Ryan

+1 L'utilizzo countsarebbe una soluzione più flessibile ed estensibile se mai avesse senso che il tuo codice accetti una raccolta implementata in modo "comune" ... IMO che potrebbe essere l'unico criterio pertinente per definire se usi counto altri modi ...
ClemC

L'enorme svantaggio della versione count()7.2 è che non può più accettare variabili vuote.
Ryan

5

In alternativa, puoi eseguire il cast della variabile come booleano (implicitamente o esplicitamente):

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

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

Questo metodo genera un messaggio E_NOTICEse la variabile non è definita, analogamente a count().

Per ulteriori informazioni, vedere la pagina del manuale PHP sui confronti dei tipi .


1
Questo è il modo migliore per controllare, usalo solo empty()se stai esplicitamente cercando di evitare di attivare un E_NOTICE (che è generalmente una cattiva idea, IMO). L'uso sfacciato di vuoto porterà a codice difettoso.
Cobby

3

La mia preferenza personale è più per l'eleganza del codice (in relazione al mio caso d'uso specifico). Sono d'accordo con Dan McG in quanto count () non risponde con il tipo di dati corretto (in questo caso booleano) per il test in questione costringendo lo sviluppatore a scrivere più codice per riempire un'istruzione "if".

Se questo ha un impatto significativo sulle prestazioni è discutibile solo per array estremamente grandi (per i quali probabilmente non si avrà abbastanza allocazione di memoria nella maggior parte delle configurazioni).

Soprattutto quando si tratta dell'array $ _POST di PHP, a mio parere sembra molto più "logico" scrivere / vedere:

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

3

Spero che questo possa aiutare qualcuno anche se ha già ricevuto una risposta (e discusso qualcosa). Nel mio scenario, so che tutti i miei array hanno tutti 7 elementi (i controlli sono stati effettuati in precedenza nel mio codice) e sto eseguendo uno array_diffche ovviamente restituisce un array di zero quando è uguale.

Avevo 34 secondi per counte 17 secondi per empty. Entrambi mi danno gli stessi calcoli quindi il mio codice va ancora bene.

Tuttavia puoi anche provare ==o ===come in PHP - Controlla se due array sono uguali . Il meglio che direi è provare countvs emptyvs == empty array, quindi vedere quale dà le tue migliori prestazioni. Nel mio caso è countstato il più lento, quindi lo sto usando emptyora ... controllerò il serializeprossimo


2

Non c'è una forte ragione per preferire count($myArray) == 0sopra empty($myArray). Hanno una semantica identica. Alcuni potrebbero trovarne uno più leggibile dell'altro. Uno potrebbe funzionare leggermente meglio dell'altro, ma non è probabile che sia un fattore significativo nella stragrande maggioranza delle applicazioni php. Per tutti gli scopi pratici, la scelta è una questione di gusti.


1
E la cosa della "performance"? Usare la spiegazione di "scopi pratici" porta a cattive abitudini. Da utilizzare countquando è necessario contare, da utilizzare emptyquando è necessario verificare se la raccolta è vuota. Ovviamente ci sono casi limite come stringhe o null, ma il programmatore deve pensare al suo codice. Potresti non essere d'accordo, ti è permesso.
Namecc

alcune volte, con count ($ myArray) se $ myArray è un booleen come un valore FALSE, il conteggio non funziona (testato su php5.3).
Mimouni

1

A volte usare il vuoto è un must. Ad esempio questo codice:

$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);

Se esegui questo codice in questo modo: http://phpfiddle.org/main/code/g9x-uwi

Ottieni questo output:

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

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

Quindi se hai countl'output glob vuoto, ottieni un output sbagliato. Dovresti controllare il vuoto.

Dalla documentazione glob :

Restituisce un array contenente i file / directory corrispondenti, un array vuoto se nessun file corrisponde o FALSE in caso di errore.
Nota: su alcuni sistemi è impossibile distinguere tra una corrispondenza vuota e un errore.

Controlla anche questa domanda: Perché contare (falso) restituisce 1?


1

Poiché una variabile analizzata come negativo sarebbe tornato int(1)concount()

Preferisco ($array === [] || !$array)testare un array vuoto.

Sì, dovremmo aspettarci un array vuoto, ma non dovremmo aspettarci una buona implementazione su funzioni senza tipi restituiti forzati.

Esempi con count()

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

0

Ho rifatto la mia mente ragazzi, grazie.

Ok, non c'è differenza tra l'utilizzo di emptye count. Tecnicamente, countdovrebbe essere usato per gli array e emptypotrebbe essere usato per gli array oltre che per le stringhe. Quindi nella maggior parte dei casi, sono intercambiabili e se vedi i documenti php, vedrai l'elenco dei suggerimenti di countse ti trovi in emptye viceversa.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.