【问题标题】:Is PHP's count() function O(1) or O(n) for arrays?PHP 的 count() 函数是 O(1) 还是 O(n) 用于数组?
【发布时间】:2011-08-15 16:02:17
【问题描述】:

count() 是否真的计算了 PHP 数组的所有元素,或者这个值是否缓存在某处并被检索到?

【问题讨论】:

  • 为什么不测试呢?做一个循环将元素添加到数组并每次计数并进行一些计时非常简单。
  • Google 关键字 - 这个问题也可以表述为:PHP count() 是遍历数组还是从数组属性中检索计数?

标签: php arrays performance


【解决方案1】:

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

/ext/standard/array.c

PHP_FUNCTION(count)调用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

【讨论】:

  • IS_CONSISTENT(ht) 做了什么?
  • 谢谢!我不太确定我应该在源代码的哪个位置查找或从何处获取源代码(无需从存储库中检查它)。
  • @Matt 如我所见,它正在检查哈希结构是否有效。它在 zend_hash.c 中定义,也是 O(1)。
  • 不能错过投票给在 PHP 源代码中寻找答案的人 :)
  • @Matt IS_CONSISTENT() 只是对数组github.com/php/php-src/blob/PHP-5.3/Zend/zend_hash.c#L51的健全性检查@
【解决方案2】:

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

编辑:您也可能会觉得这个分析很有趣:PHP Count Performance。虽然数组的长度是由数组维护的,但如果要多次调用count(),似乎还是坚持下去会更快。

【讨论】:

  • 我认为从 PHP 5 开始所做的更改可能是正确的。但是,我还没有找到证明 PHP 4 对于 count(); 是 O(n) 的证据;我只看到轶事cmets。你能找到证据吗(即 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) 以及重复函数调用的影响。
  • 进行函数调用总是比不调用慢吗?发现解释器具有内联优化,我不会感到惊讶。
  • the count method of that object will be called,你能解释一下吗
  • @SteelBrain 如果一个类实现了Countable 接口,那么调用count($object) 与调用$object-&gt;count() 是一样的。例如,请参阅3v4l.org/oYSSC
  • you're still making a function call when which is slower than not making one 这句话可能是错误的。如果是手动遍历,那就是O(n)操作。但是如果你只是想检索一个预先计算的值,那么操作是O(1)
猜你喜欢
  • 1970-01-01
  • 2011-06-01
  • 2012-02-23
  • 1970-01-01
  • 2021-02-27
  • 1970-01-01
  • 1970-01-01
  • 2013-05-04
  • 2016-04-01
相关资源
最近更新 更多