【问题标题】:Checking for empty arrays: count vs empty检查空数组:count vs empty
【发布时间】:2011-01-14 00:56:09
【问题描述】:

关于“How to tell if a PHP array is empty”的这个问题让我想到了这个问题

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

我个人的想法是,如果 2 与空数组的情况相同,则应使用 empty,因为它为布尔问题提供了布尔答案。从上面链接的问题来看,count($var) == 0 似乎是流行的方法。对我来说,虽然在技术上是正确的,但没有任何意义。例如。 问:$var,你是空的吗?答:7。嗯……

我有什么理由应该改用count == 0 还是仅仅出于个人喜好?

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

【问题讨论】:

  • 我假设您的意图是将对话仅限于数组,但可能值得注意的是,如果您使用对象(例如,实现 Countable、Iterator 等),游戏会完全改变.).
  • 空数组等于 PHP 中的 false - 不需要 empty()count()
  • 请@Cobby代码。
  • @TheRealChx101 如:if (!$myArray) { echo "array is empty"; }sandbox.onlinephpfunctions.com/code/…
  • 现在,链接问题中的流行选项是使用empty()

标签: php arrays performance standards semantics


【解决方案1】:

没有充分的理由更喜欢count($myArray) == 0 而不是empty($myArray)。它们具有相同的语义。有些人可能会发现一个比另一个更具可读性。一个可能比另一个执行得稍微好一点,但它不太可能成为绝大多数 php 应用程序的重要因素。出于所有实际目的,选择是一个品味问题。

【讨论】:

  • “性能”的东西呢?使用“实际目的”的解释会导致不良习惯。需要计数时使用count,需要检查集合是否为空时使用empty。当然也有像字符串或空值这样的极端情况,但程序员需要考虑他的代码。你可以不同意,你可以。
  • 有时,使用 count($myArray) 如果 $myArray 是一个类似于 FALSE 的布尔值,则计数不起作用(在 php5.3 上测试)。
【解决方案2】:

伙计们,我重塑了我的想法,谢谢。

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

    • 当数组为空时,这些函数确实不同。
    • @Jacco:我对此没有异议。但是如果你测试它是空的,我看不出它有什么相关性——它是一个带有布尔结果的问题,它是函数将返回的结果。关于什么被认为是空的,除非您的测试的 var 不是数组,否则看不到这些标准将如何产生错误的答案,在这种情况下,这是一个完全不同的问题。
    • @prodigitalson 我会说计数是O(1),因为 PHP 在内部存储元素的数量。看看这个答案stackoverflow.com/a/5835419/592454
    • @eliton:但仍然 - 即使性能没有差异或差异很小,如果不需要计数,为什么要使用计数?
    • empty() 对错误过于宽容。我刚刚花了 2 个小时调试一个子类,该子类在其超类的私有成员变量上测试了 empty()(超类的成员变量的范围应该受到保护,但 empty() 没有返回任何错误——结果只是应该发生了,没有发生:子类中不存在成员变量的处理方式与此成员变量(一个数组)为空的方式完全相同——即,就好像它没有元素一样)。这是有问题的,也是 PHP 过于宽容的另一个例子。
    【解决方案4】:

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

    php.net 对count 给出以下警告:

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

    换句话说,如果变量没有设置,你会从 PHP 收到通知说它是未定义的。因此,在使用count 之前,最好使用isset 检查变量。 empty 不需要这样做。

    【讨论】:

    • 有趣的是支持count的一个论点是它最初是为数组制作的......但是对象可以实现Countable,你可以将标量值传递给count()并得到一个有效的结果。
    • count() 可能为未设置的变量返回 0,但它可能也...。官方文档使用情态动词来表达其不确定性:p
    • 只是对isset() 点的评论。如果您担心 PHP 中的通知,您应该已经声明了您的数组。如果您让 PHP 动态声明您的数组,您也会在此时收到通知。我认为 php.net 上警告的真正意义在于,您不应该使用 count 来确定数组是否已声明,因为它会产生与空数组相同的结果。
    【解决方案5】:

    在确定数组是否为空时,是否有理由使用计数而不是空?

    当你需要在知道它的大小的非空数组上做某事时:

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

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

    var_dump(count(FALSE));
    

    输出:

    int 1
    

    因此,从那时起,我使用 emptyif(array() === $array) 来确保我有 array 是空的。

    【讨论】:

      【解决方案6】:

      我个人更喜欢编码优雅(与我的特定用例相关)。我同意 Dan McG 的观点,因为 count() 没有以正确的数据类型(在本例中为布尔值)响应相关测试,这迫使开发人员编写更多代码来填充“if”语句。

      这是否对性能有任何重大影响只有在非常大的数组(在大多数设置中您可能没有足够的内存分配)时才有争议。

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

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

      【讨论】:

        【解决方案7】:

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

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

        如果变量未定义,此方法会生成E_NOTICE,类似于count()

        有关详细信息,请参阅the PHP Manual page on type comparisons

        【讨论】:

        • 这是最好的检查方法,如果您明确试图避免触发 E_NOTICE(这通常是个坏主意,IMO),请仅使用empty()。公然使用空会导致代码错误。
        【解决方案8】:

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

        $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。
        注意:在某些系统上 无法区分空匹配和错误。

        还要检查这个问题: Why count(false) return 1?

        【讨论】:

          【解决方案9】:

          希望这可能对某人有所帮助,即使它已经得到了回答(并讨论了一些问题)。在我自己的场景中,我知道我所有的数组都有 7 个元素(在我的代码前面进行了检查),我正在执行 array_diff,它当然会在相等时返回一个零数组。

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

          但是,您也可以尝试=====,如PHP - Check if two arrays are equal。我想说的最好的方法是尝试count vs empty vs == empty array,然后看看哪个给你自己最好的性能。在我的情况下,count 是最慢的,所以 我现在正在使用 empty...接下来将检查 serialize

          【讨论】:

            【解决方案10】:

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

            <?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 已声明时才有效)。
            • 你的测试代码真的很糟糕。你添加了很多额外的东西,比如匿名函数调用。如果我删除并且只运行裸代码(一个接一个地循环),那么我会得到很大的不同。我的意思是在这种情况下,如果 if 语句中没有 countempty 调用,则速度会更快。然后是empty 并持续count。但是与你的裸机相比,空的要快十倍!简单数组测试:0.104662,空:0.177659,计数:PHP 5.6 上的 1.175125,否则你的代码在这个版本上给出的结果也和你提到的一样。只是结果是假的。
            • @golddragon007 他们的回答仍然比您的评论更有用,因为 1)他们对此并不讨厌 2)他们实际上展示了他们的工作。请考虑变得更好,因为这是一个帮助他人而不是侮辱他人的社区。​​span>
            • 我用过isset($x[0])empty($x)更快,但比count($x)
            【解决方案11】:

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

            【讨论】:

            • 你的意思是“empty 为这些类型的对象返回 false,即使它们没有元素”?
            • 是的。没有允许类定义它是否为“空”的接口。有一个真的没有意义。
            • +1 使用count 将是一个更灵活和可扩展的解决方案,如果您的代码接受以“通用”方式实现的集合是有意义的...... IMO 这可能是唯一相关的标准定义是否使用count 或其他方式...
            • count() 7.2 的巨大缺点是它不能再接受空变量。
            【解决方案12】:

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

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

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

            count() 的示例

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2020-03-11
              • 1970-01-01
              • 2017-08-05
              • 2022-11-16
              • 1970-01-01
              • 2013-03-26
              • 1970-01-01
              相关资源
              最近更新 更多