La fonction count () de PHP est-elle O (1) ou O (n) pour les tableaux?

96

count()Compte- t-il vraiment tous les éléments d'un tableau PHP, ou cette valeur est-elle mise en cache quelque part et est simplement récupérée?

Dexter
la source
6
Pourquoi ne pas le tester? c'est assez simple de faire une boucle qui ajoute des éléments à un tableau et compte à chaque fois et fait un chronométrage.
Marc B
3
Jetez un œil à cette question: stackoverflow.com/questions/2473989/…
The Pixel Developer
Mots clés Google - cette question pourrait également être formulée comme suit: PHP count () itère-t-il sur un tableau ou récupère-t-il le nombre de la propriété du tableau?
jave.web

Réponses:

136

Eh bien, nous pouvons regarder la source:

/ext/standard/array.c

PHP_FUNCTION(count)appelle php_count_recursive(), qui à son tour appelle zend_hash_num_elements()un tableau non récursif, qui est implémenté de cette façon:

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

    return ht->nNumOfElements;
}

Donc vous pouvez voir, c'est O(1)pour $mode = COUNT_NORMAL.

Vladislav Rastrusny
la source
6
IS_CONSISTENT(ht)Mais que fait -on?
Matthieu
1
Merci! Je ne savais pas trop où chercher dans la source ni où trouver la source (sans avoir à la récupérer dans un référentiel).
Dexter
3
@Matt Il vérifie si la structure de hachage est valide, comme je peux le voir. Il est défini dans zend_hash.c et c'est également O (1).
Vladislav Rastrusny
10
Ne peut pas manquer de voter pour quelqu'un qui cherche la réponse dans le code source de PHP :)
Lamy
1
@Matt IS_CONSISTENT () est juste une vérification de bon sens sur le tableau github.com/php/php-src/blob/PHP-5.3/Zend/zend_hash.c#L51
John Carter
7

En PHP 5+, la longueur est stockée dans le tableau donc le comptage n'est pas fait à chaque fois.

EDIT: Vous pourriez également trouver cette analyse intéressante: PHP Count Performance . Bien que la longueur du tableau soit maintenue par le tableau, il semble toujours qu'il soit plus rapide de le conserver si vous prévoyez d'appeler count()plusieurs fois.

Jberg
la source
Je pense que vous avez peut-être raison de dire que le changement a été effectué à partir de PHP 5. Cependant, je n'ai pas encore trouvé la preuve que PHP 4 était O (n) pour count (); Je ne vois que des commentaires anecdotiques. Êtes-vous capable de trouver une preuve (c'est-à-dire l'implémentation count () pour PHP 4)? Merci,
Kristopher Windsor
3

PHP stocke la taille d'un tableau en interne, mais vous faites toujours un appel de fonction quand ce qui est plus lent que de ne pas en faire un, vous voudrez donc stocker le résultat dans une variable si vous faites quelque chose comme l'utiliser dans un boucle:

Par exemple,

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

De plus, vous ne pouvez pas toujours être sûr qu'il countest appelé sur un tableau. S'il est appelé sur un objet implémentant Countablepar exemple, la countméthode de cet objet sera appelée.

mfonda
la source
En guise de suivi, vous pouvez lire josephscott.org/archives/2010/01/php-count-performance. Il détaille essentiellement comment obtenir la longueur du tableau est o (1) et l'impact des appels de fonction répétés.
TheClair
1
est-ce que faire un appel de fonction est toujours plus lent que ne pas en faire? Je ne serais pas surpris de trouver l'interpréteur pour avoir une optimisation en ligne.
corsiKa
1
the count method of that object will be called, pouvez-vous s'il vous plaît expliquer ceci un peu
Steel Brain
1
@SteelBrain si une classe implémente l' Countableinterface, alors l'appel count($object)est la même chose que l'appel $object->count(). Voir 3v4l.org/oYSSC par exemple.
mfonda
you're still making a function call when which is slower than not making oneCette déclaration peut être fausse. Si vous effectuez une traversée manuelle, c'est l' O(n)opération. Mais si vous souhaitez simplement récupérer une valeur pré-calculée, l'opération l'est O(1).
Jamshad Ahmad