Czy funkcja count () PHP jest O (1) czy O (n) dla tablic?

96

Czy count()naprawdę liczy wszystkie elementy tablicy PHP, czy też ta wartość jest gdzieś przechowywana w pamięci podręcznej i po prostu jest pobierana?

Dexter
źródło
6
Dlaczego by tego nie przetestować? wystarczy wykonać pętlę, która dodaje elementy do tablicy i zlicza za każdym razem oraz mierzy czas.
Marc B
3
Spójrz na to pytanie: stackoverflow.com/questions/2473989/…
The Pixel Developer
Słowa kluczowe Google - to pytanie można również sformułować jako: Czy PHP count () wykonuje iterację po tablicy, czy też pobiera liczbę z właściwości tablicy?
jave.web

Odpowiedzi:

136

Cóż, możemy spojrzeć na źródło:

/ext/standard/array.c

PHP_FUNCTION(count)wywołania php_count_recursive(), które z kolei wywołują zend_hash_num_elements()tablicę nierekurencyjną, która jest implementowana w ten sposób:

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

    return ht->nNumOfElements;
}

Więc widzisz, to O(1)dla $mode = COUNT_NORMAL.

Vladislav Rastrusny
źródło
6
Co jednak robi IS_CONSISTENT(ht)?
Matthew,
1
Dzięki! Nie byłem do końca pewien, gdzie w źródle powinienem szukać ani skąd wziąć źródło (bez konieczności sprawdzania go z repozytorium).
Dexter
3
@Matt Sprawdza, czy struktura hash jest prawidłowa, jak widzę. Jest zdefiniowany w zend_hash.c i jest również O (1).
Vladislav Rastrusny
10
Nie można przegapić głosowania na kogoś, kto szuka odpowiedzi w kodzie źródłowym PHP :)
Lamy
1
@Matt IS_CONSISTENT () to po prostu sprawdzenie poczytalności w tablicy github.com/php/php-src/blob/PHP-5.3/Zend/zend_hash.c#L51
John Carter
7

W PHP 5+ długość jest przechowywana w tablicy, więc zliczanie nie jest wykonywane za każdym razem.

EDYCJA: Ta analiza może być również interesująca: Wydajność liczenia PHP . Chociaż długość tablicy jest utrzymywana przez tablicę, nadal wydaje się, że szybsze jest jej zatrzymanie, jeśli zamierzasz wywoływać count()wiele razy.

jberg
źródło
Myślę, że możesz mieć rację, że zmiana została wprowadzona począwszy od PHP 5. Jednak nie znalazłem jeszcze dowodu, że PHP 4 było O (n) dla count (); Widzę tylko anegdotyczne komentarze. Czy jesteś w stanie znaleźć dowód (tj. Implementację count () dla PHP 4)? Dzięki,
Kristopher Windsor
3

PHP przechowuje wewnętrznie rozmiar tablicy, ale nadal wywołujesz funkcję, która jest wolniejsza niż jej brak, więc będziesz chciał przechowywać wynik w zmiennej, jeśli robisz coś takiego jak użycie jej w pętla:

Na przykład,

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

Ponadto nie zawsze można mieć pewność, countże wywoływana jest tablica. Jeśli zostanie wywołana na obiekcie, który implementuje Countablena przykład, countzostanie wywołana metoda tego obiektu.

mfonda
źródło
W ramach kontynuacji możesz przeczytać josephscott.org/archives/2010/01/php-count-performance. W zasadzie szczegółowo opisuje, w jaki sposób uzyskanie długości tablicy wynosi o (1) i jaki jest wpływ powtarzanych wywołań funkcji.
TheClair
1
czy wywołanie funkcji jest zawsze wolniejsze niż jej brak? Nie zdziwiłbym się, gdyby interpreter miał wbudowaną optymalizację.
corsiKa
1
the count method of that object will be called, czy możesz to trochę wyjaśnić
Steel Brain
1
@SteelBrain Jeśli klasa implementuje Countableinterfejs, wywołanie count($object)jest tym samym, co wywołanie $object->count(). Zobacz na przykład 3v4l.org/oYSSC .
mfonda,
you're still making a function call when which is slower than not making oneTo stwierdzenie może być błędne. Jeśli wykonujesz ręczne przechodzenie, to jest O(n)operacja. Ale jeśli chcesz tylko pobrać wstępnie obliczoną wartość, operacja jest O(1).
Jamshad Ahmad