Функція count () PHP - O (1) або O (n) для масивів?


96

Чи count()насправді підраховуються всі елементи масиву PHP, чи це значення десь кешоване і просто отримується?


6
Чому б не перевірити? досить просто зробити цикл, який додає елементи до масиву і підраховує кожен раз, і виконує деяку синхронізацію.
Marc B

3
Погляньте на це питання: stackoverflow.com/questions/2473989/…
розробник Pixel

Ключові слова Google - це запитання також можна сформулювати так: Чи перелічує PHP () ітерацію над масивом або отримує рахунок із властивості масиву?
jave.web

Відповіді:


136

Ну, ми можемо подивитися на джерело:

/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.


6
Що ж IS_CONSISTENT(ht)робити?
Метью

1
Дякую! Я не був точно впевнений, куди у джерелі слід шукати або де взяти джерело (без необхідності перевіряти його зі сховища).
Декстер,

3
@Matt Перевіряє, чи правильна структура хешу, як я бачу. Це визначено в zend_hash.c, і це також O (1).
Владислав Раструсний

10
Не можу пропустити голосування за когось, хто шукає відповідь у вихідному коді PHP :)
Ламі

1
@Matt IS_CONSISTENT () - це лише перевірка осудності масиву github.com/php/php-src/blob/PHP-5.3/Zend/zend_hash.c#L51
Джон Картер

7

У PHP 5+ довжина зберігається в масиві, тому підрахунок не проводиться кожного разу.

РЕДАГУВАТИ: Цей аналіз вам також може стати цікавим: продуктивність підрахунку PHP . Незважаючи на те, що довжина масиву підтримується масивом, все одно здається, що швидше за нього втриматися, якщо ви збираєтеся телефонувати count()багато разів.


Я думаю, ви можете помилитись, що зміна була внесена, починаючи з PHP 5. Однак я ще не знайшов доказ того, що PHP 4 був O (n) для count (); Я просто бачу анекдотичні коментарі. Чи можете ви знайти доказ (тобто реалізацію count () для PHP 4)? Дякую,
Крістофер Віндзор,

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

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).
Джамшад Ахмад,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.