Diziler için PHP'nin count () fonksiyonu O (1) veya O (n) mudur?


98

count()Gerçekten bir PHP dizisinin tüm öğelerini sayıyor mu , yoksa bu değer bir yerde önbelleğe alınıyor ve yeni mi alınıyor?


7
Neden test etmiyorsun? Bir diziye eleman ekleyen ve her seferinde sayan ve biraz zamanlama yapan bir döngü yapmak yeterince basittir.
Marc B


Google anahtar kelimeleri - bu soru şu şekilde de formüle edilebilir: PHP count () dizi üzerinde yineleniyor mu yoksa dizi özelliğinden sayımı alıyor mu?
jave.web

Yanıtlar:


138

Peki, kaynağa bakabiliriz:

/ext/standard/array.c

PHP_FUNCTION(count)php_count_recursive()sırayla zend_hash_num_elements()özyinelemeli olmayan diziyi çağıran çağrılar , bu şekilde uygulanır:

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

    return ht->nNumOfElements;
}

Böylece görebilirsiniz, bunun O(1)için $mode = COUNT_NORMAL.


6
Ne anlama geliyor IS_CONSISTENT(ht)?
Matthew

1
Teşekkürler! Kaynakta nereye bakmam gerektiğinden veya kaynağı nereden alacağımdan tam olarak emin değildim (bir depodan kontrol etmek zorunda kalmadan).
Dexter

3
@Matt Gördüğüm gibi hash yapısının geçerli olup olmadığını kontrol ediyor. Zend_hash.c'de tanımlanmıştır ve ayrıca O (1) 'dir.
Vladislav Rastrusny

10
PHP'nin kaynak kodunda cevap arayan birine oy vermeyi kaçıramazsınız :)
Yasen


7

PHP 5+ sürümünde uzunluk dizide saklanır, böylece sayım her seferinde yapılmaz.

DÜZENLEME: Bu analizi ilginç de bulabilirsiniz: PHP Sayım Performansı . Dizinin uzunluğu dizi tarafından korunsa da, count()birçok kez arayacaksanız, diziyi tutmak daha hızlı gibi görünüyor .


Sanırım bu değişikliğin PHP 5'ten itibaren yapıldığı konusunda haklısınız. Ancak, PHP 4'ün count () için O (n) olduğuna dair kanıt bulamadım; Sadece anekdotlu yorumlar görüyorum. İspat (yani PHP 4 için count () uygulaması) bulabiliyor musunuz? Teşekkürler,
Kristopher Windsor

3

PHP bir dizinin boyutunu dahili olarak depolar, ancak yine de bir işlev çağrısı yapmadığınızdan daha yavaş olan bir işlev çağrısı yapıyorsunuz, bu nedenle, diziyi bir dizide kullanmak gibi bir şey yapıyorsanız sonucu bir değişkende saklamak isteyeceksiniz. döngü:

Örneğin,

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

Ek countolarak, bir dizide çağrıldığından her zaman emin olamazsınız . CountableÖrneğin uygulayan bir nesnede çağrılırsa, counto nesnenin yöntemi çağrılır.


Bir takip olarak josephscott.org/archives/2010/01/php-count-performance okumak isteyebilirsiniz Temel olarak dizi uzunluğunun nasıl o (1) olduğunu ve tekrarlanan işlev çağrılarının etkisini detaylandırır.
TheClair

1
bir işlev çağrısı yapmak, yapmamaktan her zaman daha yavaş mıdır? Satır içi optimizasyona sahip tercümanı bulmak beni şaşırtmaz.
corsiKa

1
the count method of that object will be called, lütfen bunu biraz açıklayabilir misin
Steel Brain

1
@SteelBrain bir sınıf Countablearabirimi uygularsa, çağrı çağırmakla count($object)aynı şeydir $object->count(). Örneğin 3v4l.org/oYSSC'ye bakın .
mfonda

you're still making a function call when which is slower than not making oneBu ifade yanlış olabilir. Manüel geçiş yapıyorsanız, bu O(n)işlemdir. Ancak sadece önceden hesaplanmış bir değeri almak istiyorsanız, o zaman işlem olur O(1).
Jamshad Ahmad
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.