PHP的count()函数是数组的O(1)还是O(n)?


96

count()真的要计算PHP数组的所有元素,还是将此值缓存在某个地方并被检索?


6
为什么不测试呢?它很简单,只需执行一个循环即可将元素添加到数组中,并在每次计数时进行一些计时。
Marc B


Google关键字-这个问题也可以表述为:PHP count()是否在数组上迭代还是从array属性中检索计数?
jave.web 2015年

Answers:


136

好吧,我们可以看看源代码:

/ext/standard/array.c

PHP_FUNCTION(count)call php_count_recursive(),这反过来又需要zend_hash_num_elements()非递归数组,该数组是通过以下方式实现的:

ZEND_API int zend_hash_num_elements(const HashTable *ht)
{
    IS_CONSISTENT(ht);

    return ht->nNumOfElements;
}

所以你可以看到,它O(1)$mode = COUNT_NORMAL


6
怎么IS_CONSISTENT(ht)办?
马修

1
谢谢!我不确定应该在源代码中的哪个位置或从哪里获取源代码(而不必从存储库中检出)。
德克斯特

3
@Matt,正如我所见,它正在检查哈希结构是否有效。它是在zend_hash.c中定义的,也是O(1)。
Vladislav Rastrusny 2011年

10
不能错过为在PHP源代码中寻找答案的人投票的方法:)
Lamy 2012年

1
@Matt IS_CONSISTENT()只是对数组github.com/php/php-src/blob/PHP-5.3/Zend/zend_hash.c#L51
John Carter

7

在PHP 5+中,长度存储在数组中,因此不会每次都进行计数。

编辑:您可能还会发现此分析很有趣:PHP Count Performance。尽管数组的长度由数组维护,但如果要count()多次调用,则保持它的速度似乎更快。


我认为从PHP 5开始进行更改可能是正确的。但是,我还没有发现PHP 4对于count()是O(n)的证明。我只是看到轶事评论。您是否可以找到证明(即PHP 4的count()实现)?谢谢,
克里斯托弗·温莎

3

PHP在内部存储数组的大小,但是当您进行函数调用比不进行数组调用要慢时,您仍在进行函数调用,因此,如果您要在数组中使用它,则需要将结果存储在变量中循环:

例如,

$cnt = count($array);
for ($i =0; $i < $cnt; $i++) {
   foo($array[$i]);
}

另外,您不能总是确定count正在数组上被调用。如果在Countable例如实现的对象上调用它,则将调用该对象的count方法。


作为后续,您可能需要阅读josephscott.org/archives/2010/01/php-count-performance它基本上详细说明了如何获取数组长度为o(1)以及重复函数调用的影响。
TheClair

1
进行函数调用总是比不进行函数调用慢吗?我对找到具有内联优化功能的解释器并不感到惊讶。
corsiKa 2011年

1
the count method of that object will be called,您能解释一下吗
Steel Brain

1
@SteelBrain(如果一个类实现了该Countable接口),则调用count($object)与调用相同$object->count()。例如,请参见3v4l.org/oYSSC
mfonda

you're still making a function call when which is slower than not making one这个说法可能是错误的。如果您要进行手动遍历,那就是O(n)操作。但是,如果您只想检索预先计算的值,则操作为O(1)
Jamshad Ahmad
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.