检查空数组:计数与空


98

这个关于“ 如何判断PHP数组是否为空 ”的问题让我想到了这个问题

确定数组是否为空时,count是否应该使用代替理由empty

我个人认为如果在使用空数组的情况下2是否相等,empty因为它为布尔问题提供了布尔答案。从上面链接的问题来看,这似乎count($var) == 0是流行的方法。对我来说,尽管在技术上是正确的,但没有任何意义。例如:$ var,您是空的吗?答:7。嗯...

是我应该count == 0改用还是仅出于个人喜好?

正如其他人在注释中指出的那样,现在删除的答案count将对大型数组产生性能影响,因为它将必须计算所有元素,而empty一旦知道它不为空就可以停止。因此,如果在这种情况下它们给出相同的结果,但count效率可能很低,那么为什么还要使用count($var) == 0


我假设您的意图是仅将对话限制为数组,但值得注意的是,如果您使用的是对象(例如,实现Countable,Iterator等),则游戏会完全改变。

8
空数组等于falsePHP中的-不需要empty()or count()
科比2012年

请@Cobby代码。
TheRealChx101 '17

@ TheRealChx101就像做一样:if (!$myArray) { echo "array is empty"; } sandbox.onlinephpfunctions.com/code/…–
Cobby

如今,链接问题中的热门选项是使用empty()
PhoneixS

Answers:


97

我一般用empty。我不确定为什么人们会真正使用count-如果数组很大,那么count需要更长的时间/会有更多的开销。如果您只需要知道数组是否为空,则使用空。


4
当数组不为空时,这些函数的确不同。
雅科

2
@Jacco:我没有争议。但是,如果您测试它为空,则我看不到它有什么意义-它是一个布尔结果的问题,即函数将返回什么。关于什么被认为是空的,不要看这些标准将如何产生错误的答案,除非您的测试变量不是一个数组,在这种情况下那就是完全不同的问题。
prodigitalson

23
@prodigitalson我会说count是O(1),因为PHP在内部存储了元素数量。看看这个答案stackoverflow.com/a/5835419/592454
elitalon 2012年

4
@eliton:但是仍然-即使在性能上没有差异或差异很小,如果您不需要计数,为什么还要使用计数呢?
prodigitalson

4
empty()太宽容了错误。我只花了2个小时调试一个子类,该子类在其超类的私有成员变量上测试了empty()(超类的成员变量的范围应该受到保护,但是empty()没有返回错误)-结果就是,应该发生了什么,没有发生过:子类中成员变量的不存在与该成员变量(一个数组)为空(即,好像没有元素)完全一样。这是有问题的,PHP的另一个示例太宽容了。
马修·斯莱曼

46

我很想知道哪个实际上更快,所以我编写了一个简单的脚本来对那些函数进行基准测试。

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

自从我这样做以来,我还尝试检查执行通常与count()/ empty()相关联的操作的性能

使用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

使用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

结论(如果您使用的是PHP):

  1. 在这两种情况下,empty()都比count()快得多,它们具有一个空且填充的数组

  2. count()对完整或空数组执行相同的操作。

  3. 执行简单的IF或仅执行布尔运算是相同的。

  4. IF / ELSE的效率比(?:)略高。除非您使用中间的表达式进行数十亿次迭代,否则它是无关紧要的。

结论(如果您使用的是HHVM):

  1. empty()比count()快了一点,但微不足道。

    [其余与PHP中相同]

结论的结论是,如果您只需要知道数组是否为空,请始终使用empty();。

这只是一个好奇的测试,只是在没有考虑很多事情的情况下完成的。这只是概念的证明,可能无法反映生产中的操作。


感谢您提供的示例测试代码。...我刚刚使用它,发现它if($x){的速度比if(empty($x)){(仅当您知道$x已声明的情况下才有效)。
Redzarf

您的测试代码确实很糟糕。您添加了许多其他内容,例如匿名函数调用。如果删除并只运行裸代码(彼此循环),那么我会得到很大的不同。我的意思是在这种情况下,如果if语句中没有countand empty调用,则速度更快。然后它来了,empty并持续了count。但是,与您裸露的箱子相比,空箱子要快十倍!简单数组测试:PHP 5.6上的简单数组测试:0.104662,空:0.177659,计数:1.175125,否则,您的代码在此版本上的结果也与您提到的相同。只是假的结果。
golddragon007

16

我认为这只是个人喜好。有人可能会说empty更快(例如http://jamessocol.com/projects/count_vs_empty.php),而其他人可能会说count更好,因为它最初是为数组制作的。empty比较笼统,可以应用于其他类型。

php.net给出以下警告count

对于未设置的变量,count()可能返回0,但对于已用空数组初始化的变量,它也可能返回0。使用isset()测试是否设置了变量。

换句话说,如果未设置变量,PHP会通知您该变量未定义。因此,在使用之前count,最好使用来检查变量isset。不需要这样做empty


3
有趣的count是,赞成使用的参数是它最初是为数组制作的...但是对象可以实现Countable,并且您可以将标量值传递给count()并获得有效的结果。

1
COUNT()用于未设置变量返回0,但它可能也......。官方文档使用情态动词表达其不确定性:p
nawfal

只是关于这isset()一点的评论。如果您担心PHP中的通知,则应该已经声明了数组。如果让PHP动态声明数组,那么您也会在此时得到通知。我认为php.net上警告的真正含义是,您不应使用它count来确定是否已声明数组,因为它产生的结果与空数组相同。
诺亚·邓肯

12

确定数组是否为空时,是否有理由应使用count而不是empty?

有一种情况,当您需要在非空数组上执行某些操作时就知道它的大小:

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

但是我不建议您使用count,除非您100%确信要计数的是数组。最近我一直在调试代码,错误函数返回FALSE而不是空数组,发现的是:

var_dump(count(FALSE));

输出:

int 1

因此,从那时起,我一直在使用emptyif(array() === $array)确保数组为空。


6

count()似乎可以与实现的类似数组的接口更好地协作ArrayAccess/Countableempty()对于这些对象,即使它们没有元素也返回true。通常,这些类将实现Countable接口,因此如果问题是“此集合是否包含元素?” 如果不对实现做任何假设,那么这count()是一个更好的选择。


您的意思是“ 即使这些对象没有元素,它们也会empty返回false ”?
alexw

是。没有接口允许类定义它是否为“空”。而且,只有一个没有意义。
瑞安

+1使用count将是一种更加灵活和可扩展的解决方案,只要它对使代码接受以“通用”方式实现的集合有意义,那么... IMO可能是定义是否使用count或其他方式的唯一相关标准...
ClemC

count()7.2开始的巨大缺点是它不能再使用空变量。
瑞安

5

另外,您可以将变量强制转换为布尔值(隐式或显式):

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

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

E_NOTICE如果未定义变量,则此方法的确会生成count()

有关更多信息,请参见有关类型比较的PHP手册页


1
这是最好的检查方法,仅empty()当您明确尝试避免触发E_NOTICE 时才使用(通常,这是一个坏主意,IMO)。公然使用空将导致错误的代码。
科比2012年

3

我的个人偏爱更多是为了编写优雅的代码(相对于我的特定用例)。我同意Dan McG的观点,因为count()没有针对测试中正确的数据类型(在这种情况下为boolean)进行响应,从而迫使开发人员编写更多代码来填充'if'语句。

这是否会对性能产生重大影响,只有在超大型阵列(在大多数设置中,您可能没有足够的内存分配)上才有争议。

特别是当涉及到PHP的$ _POST数组时,我认为写/看似乎更“合乎逻辑”:

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

3

希望即使已经回答(并讨论了一些内容),这也可能对某人有所帮助。在我自己的场景中,我知道我的所有数组都具有7个元素(在代码中进行了较早的检查),并且我执行的array_diff当然是在相等时返回零数组。

我有34秒count,有17秒empty。两者都给我相同的计算,所以我的代码仍然可以。

但是,您也可以尝试在PHP中使用==or或as-检查两个数组是否相等。我会说的最好是vs vs vs ,然后看看哪一个能给您带来最好的表现。在我的情况是最慢的所以我使用的,现在 ...将检查下一个===countempty== empty arraycountemptyserialize


2

没有强有力的理由,更喜欢count($myArray) == 0empty($myArray)。它们具有相同的语义。有些人可能会发现其中一种更具可读性。一个可能比另一个性能稍好一些,但在绝大多数php应用程序中,这可能不是一个重要因素。对于所有实际目的,选择都取决于品味。


1
那“性能”呢?使用“实际目的”的解释会导致不良习惯。使用count时,你需要计算,使用empty时您需要检查,如果集合为空。当然,有一些极端情况,例如字符串或空值,但是程序员需要考虑一下他的代码。您可能不同意,您可以允许。
Namek 2014年

有时,使用count($ myArray)如果$ myArray是像值FALSE这样的布尔值,则该计数不起作用(在php5.3上进行了测试)。
Mimouni

1

有时必须使用空。例如此代码:

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

如果您像这样运行此代码:http : //phpfiddle.org/main/code/g9x-uwi

您得到以下输出:

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

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

因此,如果您count的glob输出为空,则会得到错误的输出。您应该检查是否为空。

glob文档中:

返回一个包含匹配文件/目录的数组,如果没有文件匹配则返回一个空数组,否则返回FALSE。
注意:在某些系统上,无法区分空匹配和错误。

还要检查以下问题: 为什么count(false)返回1?


1

由于变量解析为负将返回int(1)count()

我更喜欢($array === [] || !$array)测试一个空数组。

是的,我们应该期望一个空数组,但是我们不应该期望在没有强制返回类型的函数上实现良好的实现。

例子 count()

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

0

我重塑了我的头脑,谢谢。

好的,empty和的用法没有区别count。从技术上讲,count应该用于数组,并且empty可以用于数组以及字符串。因此,在大多数情况下,它们是可互换的,如果您看到php文档,则会看到有关count您是否在的建议列表,empty反之亦然。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.