Verificando matrizes vazias: contagem vs vazio

98

Esta questão em ' Como saber se um array PHP está vazio ' me fez pensar nesta questão

Existe um motivo que countdeve ser usado em vez de emptydeterminar se um array está vazio ou não?

Minha opinião pessoal seria se os 2 são equivalentes para o caso de matrizes vazias que você deve usar emptyporque dá uma resposta booleana a uma pergunta booleana. Pela pergunta vinculada acima, parece que count($var) == 0é o método popular. Para mim, embora tecnicamente correto, não faz sentido. Por exemplo, Q: $ var, você está vazio? A: 7 . Hmmm ...

Há algum motivo para eu usar em count == 0vez disso ou apenas uma questão de gosto pessoal?

Conforme apontado por outros em comentários para uma resposta agora excluída, countterá impactos no desempenho para grandes arrays porque terá que contar todos os elementos, enquanto emptypode parar assim que souber que não está vazio. Portanto, se eles fornecem os mesmos resultados neste caso, mas countsão potencialmente ineficientes, por que usaríamos count($var) == 0?

Dan McGrath
fonte
Estou assumindo que sua intenção é limitar a conversa exclusivamente a arrays, mas pode valer a pena notar que o jogo muda completamente se você estiver trabalhando com objetos (por exemplo, que implementam Countable, Iterator, etc.).
8
Um array vazio é igual a falseem PHP - não há necessidade de empty()ou count().
Cobby
@Cobby Code, por favor.
TheRealChx101 de
@ TheRealChx101 Como em, basta fazer: if (!$myArray) { echo "array is empty"; } sandbox.onlinephpfunctions.com/code/…
Cobby
Hoje em dia, a opção popular na questão vinculada é usar empty().
PhoneixS

Respostas:

97

Eu geralmente uso empty. Não sei por que as pessoas usariam a contagem - se a matriz for grande, a contagem leva mais tempo / tem mais sobrecarga. Se você simplesmente precisa saber se o array está vazio ou não, use empty.

filho pródigo
fonte
4
Essas funções realmente diferem quando o array não está vazio.
Jacco
2
@Jacco: Não estou contestando isso. Mas se você está testando está vazio, não vejo a relevância disso - é uma pergunta com um resultado booleano que é o que a função retornará. Em relação ao que é considerado vazio, não veja como esses critérios produziriam a resposta errada, a menos que o var seu teste não seja um array, caso em que isso é um problema totalmente diferente.
prodigitalson
23
@prodigitalson eu diria que a contagem é O(1), já que o PHP armazena o número de elementos internamente. Confira esta resposta stackoverflow.com/a/5835419/592454
elitalon
4
@eliton: mas ainda assim - mesmo se houver pouca ou nenhuma diferença no desempenho, por que usar a contagem se você não precisa da contagem?
prodigitalson
4
empty () é muito tolerante com erros. Acabei de passar 2 horas depurando uma subclasse que testou empty () em uma variável de membro privada de sua superclasse (o escopo da variável de membro da superclasse DEVE ter sido protegido, mas empty () não retornou erros - o resultado foi simplesmente algo que deveria aconteceram, não aconteceram: a não existência da variável membro na subclasse foi tratada exatamente da mesma maneira como se esta variável membro, um array, estivesse vazia - ou seja, como se não tivesse elementos). Isso é problemático, e outro exemplo de PHP sendo muito tolerante.
Matthew Slyman,
46

Eu estava curioso para ver qual era realmente mais rápido, então fiz um script simples para comparar essas funções.

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

Já que estava fazendo isso, também tentei verificar o desempenho fazendo operações que normalmente estariam associadas a count () / empty ()

Usando 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

Usando 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

Conclusões se você estiver usando PHP:

  1. empty () é muito mais rápido que count () em ambos os cenários, com um array vazio e preenchido

  2. count () executa o mesmo com um array cheio ou vazio.

  3. Fazer uma operação IF simples ou apenas booleana é o mesmo.

  4. IF / ELSE é ligeiramente mais eficiente do que (?:). A menos que você esteja fazendo bilhões de iterações com expressões no meio, é completamente insignificante.

Conclusões se você estiver usando HHVM:

  1. empty () é um pouquinho mais rápido do que count (), mas insignificantemente.

    [O resto é igual ao PHP]

Concluindo a conclusão, se você só precisa saber se o array está vazio, sempre use empty ();

Este foi apenas um teste curioso feito simplesmente sem levar muitas coisas em consideração. É apenas uma prova de conceito e pode não refletir as operações em produção.

Satake
fonte
Obrigado pelo código de teste de amostra .... Acabei de usá-lo e descobri que if($x){é mais rápido do que if(empty($x)){(só funciona se você souber que $xfoi declarado).
Redzarf
Seu código de teste é muito ruim. Você está adicionando muitas coisas adicionais, como uma chamada de função anônima. Se eu remover e apenas executar o código vazio (para um ciclo após o outro), obtenho uma grande diferença. E eu quero dizer, nesse caso, o mais rápido se não houver chamadas counte emptyna instrução if. Então vem o emptye dura o count. Mas em comparação com o seu caso, o vazio é dez vezes mais rápido! Teste de array simples: 0,104662, vazio: 0,177659, contagem: 1,175125 no PHP 5.6, caso contrário, seu código fornece o mesmo resultado nesta versão, como o mencionado. São resultados falsos.
golddragon007
16

Acho que é apenas preferência pessoal. Algumas pessoas podem dizer que emptyé mais rápido (por exemplo, http://jamessocol.com/projects/count_vs_empty.php ), enquanto outros podem dizer que counté melhor, já que foi feito originalmente para arrays. emptyé mais geral e pode ser aplicado a outros tipos.

php.net dá o seguinte aviso para count:

count () pode retornar 0 para uma variável que não foi definida, mas também pode retornar 0 para uma variável que foi inicializada com um array vazio. Use isset () para testar se uma variável está definida.

Em outras palavras, se a variável não for definida, você receberá um aviso do PHP informando que ela é indefinida. Portanto, antes de usar count, é preferível verificar a variável com isset. Isso não é necessário com empty.

Laurent le Beau-Martin
fonte
3
É interessante que um argumento a favor de counté que ele foi originalmente feito para arrays ... mas os objetos podem implementar Countablee você pode passar valores escalares count()e obter um resultado válido.
1
count () pode retornar 0 para uma variável que não está definido, mas pode também ... . Documentação oficial usando verbos modais para expressar sua incerteza: p
nawfal
Apenas um comentário sobre o isset()ponto. Se você está preocupado com avisos em PHP, você já deve ter declarado seu array. Se você permitir que o PHP declare dinamicamente seu array, você receberá um aviso nesse ponto também. Acho que o verdadeiro ponto do aviso no php.net é que você não deve usar countpara determinar se um array foi declarado ou não, pois produz o mesmo resultado que um array vazio faria.
Noah Duncan,
12

Existe um motivo pelo qual count deve ser usado em vez de vazio ao determinar se um array está vazio ou não?

Há, quando você precisa fazer algo em uma matriz não vazia sabendo seu tamanho:

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

Mas eu não recomendaria usar count, a menos que você tenha 100% de certeza de que o que você está contando é um array. Ultimamente tenho depurado o código, onde a função de erro estava retornando em FALSEvez do array vazio, e o que descobri foi:

var_dump(count(FALSE));

resultado:

int 1

Então desde então estou usando emptyou if(array() === $array)para ter certeza que tenho array que está vazio.

dev-null-morador
fonte
6

count()parece funcionar melhor com interfaces semelhantes a array que implementam ArrayAccess/Countable. empty()retorna true para esses tipos de objetos, mesmo se eles não tiverem elementos. Normalmente, essas classes implementam a Countableinterface, portanto, se a pergunta for "Esta coleção contém elementos?" sem fazer uma suposição sobre a implementação, então count()é uma opção melhor.

Ryan
fonte
Você quer dizer " emptyretorna falso para esses tipos de objetos, mesmo se eles não tiverem elementos"?
alexw
Sim. Não há interface que permita a uma classe definir se está "vazia" ou não. E realmente não faria sentido haver um.
Ryan
+1 Usar countseria uma solução mais flexível e extensível se alguma vez fizesse sentido para o seu código aceitar uma coleção implementada de uma forma "comum" ... IMO que pode ser o único critério pertinente para definir se você usa countou de outras maneiras ...
ClemC
A grande desvantagem do count()7.2 é que ele não pode mais aceitar variáveis ​​vazias.
Ryan
5

Como alternativa, você pode converter a variável como booleana (implícita ou explicitamente):

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

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

Este método gera um E_NOTICEse a variável não for definida, de forma semelhante a count().

Para obter mais informações, consulte a página do Manual do PHP sobre comparações de tipo .


fonte
1
Esta é a melhor maneira de verificar, use apenas empty()se estiver explicitamente tentando evitar o disparo de um E_NOTICE (o que geralmente é uma má ideia, IMO). Usar o vazio descaradamente levará a código com erros.
Cobby
3

Minha preferência pessoal é mais elegância de codificação (em relação ao meu caso de uso específico). Concordo com Dan McG na medida em que count () não está respondendo com o tipo de dados correto (neste caso, booleano) para o teste em questão, forçando o desenvolvedor a escrever mais código para preencher uma instrução 'if'.

Se isso tem algum impacto significativo no desempenho, só é discutível para arrays extremamente grandes (para os quais você provavelmente não terá alocação de memória suficiente na maioria das configurações).

Particularmente quando se trata do array $ _POST do PHP, parece muito mais "lógico" na minha opinião escrever / ver:

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

Espero que isso possa ajudar alguém, embora já tenha sido respondido (e debatido um pouco). Em meu próprio cenário, sei que todos os meus arrays têm 7 elementos (verificações foram feitas anteriormente em meu código) e estou executando um array_diffque, é claro, retorna um array de zero quando igual.

Eu tive 34 segundos para count e 17 segundos para empty. Ambos me fornecem os mesmos cálculos, então meu código ainda está bom.

No entanto, você também pode tentar o ==ou ===como no PHP - Verifique se dois arrays são iguais . O melhor que eu diria é tentar countvs emptyvs == empty array, então ver qual oferece seus melhores perfs. No meu caso countfoi o mais lento então estou usando emptyagora ... irei verificando a serializeseguir

xchiltonx
fonte
2

Não há nenhuma razão forte para preferir count($myArray) == 0mais empty($myArray). Eles têm semânticas idênticas. Alguns podem achar um mais legível do que o outro. Um pode ter um desempenho ligeiramente melhor do que o outro, mas não é provável que seja um fator significativo na grande maioria dos aplicativos php. Para todos os efeitos práticos, a escolha é uma questão de gosto.

Asaph
fonte
1
E quanto ao "desempenho"? Usar a explicação de "propósitos práticos" leva a maus hábitos. Use countquando precisar contar, use emptyquando precisar verificar se a coleção está vazia. Claro que existem casos extremos como strings ou nulos, mas o programador precisa pensar sobre seu código. Você pode discordar, você pode.
Namekusei,
algumas vezes, com count ($ myArray) se $ myArray for um booleen como um valor FALSE, a contagem não está funcionando (testado em php5.3).
Mimouni
1

Às vezes, usar o empty é obrigatório. Por exemplo, este código:

$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 você executar este código assim: http://phpfiddle.org/main/code/g9x-uwi

Você obtém esta saída:

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

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

Então, se você count usar a saída glob vazia, obterá uma saída errada. Você deve verificar se há vazio.

Da documentação glob :

Retorna um array contendo os arquivos / diretórios correspondentes, um array vazio se nenhum arquivo for correspondido ou FALSE em caso de erro.
Nota: Em alguns sistemas, é impossível distinguir entre correspondência vazia e um erro.

Verifique também esta pergunta: Por que contar (falso) retorna 1?

trante
fonte
1

Uma vez que uma variável analisada como negativa retornaria int(1) comcount()

eu prefiro ($array === [] || !$array) testar um array vazio.

Sim, devemos esperar um array vazio, mas não devemos esperar uma boa implementação em funções sem tipos de retorno forçados.

Exemplos com count()

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

Eu refiz minha mente, pessoal, obrigado.

Ok, não há diferença entre o uso de emptye count. Tecnicamente, countdeve ser usado para arrays e emptypode ser usado para arrays e também para strings. Então, na maioria dos casos, eles são intercambiáveis ​​e se você ver os documentos php, verá a lista de sugestões de countse você está em emptye vice-versa.

Sarfraz
fonte