¿La función count () de PHP es O (1) u O (n) para matrices?

96

¿ count()Realmente cuenta todos los elementos de una matriz PHP, o este valor se almacena en caché en algún lugar y simplemente se recupera?

Diestro
fuente
6
¿Por qué no probarlo? es bastante simple hacer un ciclo que agrega elementos a una matriz y cuenta cada vez y cronometra.
Marc B
3
Eche un vistazo a esta pregunta: stackoverflow.com/questions/2473989/…
The Pixel Developer
Palabras clave de Google: esta pregunta también se podría formular como: ¿PHP count () itera sobre la matriz o recupera el recuento de la propiedad de la matriz?
jave.web

Respuestas:

136

Bueno, podemos mirar la fuente:

/ext/standard/array.c

PHP_FUNCTION(count)llamadas php_count_recursive(), que a su vez requiere zend_hash_num_elements()una matriz no recursiva, que se implementa de esta manera:

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

    return ht->nNumOfElements;
}

Entonces puedes ver, es O(1)para $mode = COUNT_NORMAL.

Vladislav Rastrusny
fuente
6
¿ IS_CONSISTENT(ht)Pero qué hace ?
Mateo
1
¡Gracias! No estaba muy seguro de en qué parte de la fuente debería buscar o dónde obtener la fuente (sin tener que buscarla en un repositorio).
Dexter
3
@Matt Está comprobando si la estructura hash es válida, como puedo ver. Está definido en zend_hash.cy también es O (1).
Vladislav Rastrusny
10
No puedo dejar de votar por alguien que busque la respuesta en el código fuente de PHP :)
Lamy
1
@Matt IS_CONSISTENT () es solo una verificación de cordura en la matriz github.com/php/php-src/blob/PHP-5.3/Zend/zend_hash.c#L51
John Carter
7

En PHP 5+, la longitud se almacena en la matriz, por lo que el conteo no se realiza cada vez.

EDITAR: También puede encontrar este análisis interesante: PHP Count Performance . Aunque la longitud de la matriz se mantiene mediante la matriz, todavía parece que es más rápido mantenerla si va a llamar count()muchas veces.

jberg
fuente
Creo que puede tener razón en que el cambio se realizó a partir de PHP 5. Sin embargo, todavía no he encontrado la prueba de que PHP 4 fuera O (n) para count (); Solo veo comentarios anecdóticos. ¿Puede encontrar pruebas (es decir, la implementación count () para PHP 4)? Gracias,
Kristopher Windsor
3

PHP almacena el tamaño de una matriz internamente, pero aún está haciendo una llamada de función cuando es más lento que no hacer una, por lo que querrá almacenar el resultado en una variable si está haciendo algo como usarlo en un lazo:

Por ejemplo,

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

Además, no siempre puede estar seguro de que countse está llamando en una matriz. Si se llama a un objeto que se implementa, Countablepor ejemplo, countse llamará al método de ese objeto.

mfonda
fuente
Como seguimiento, es posible que desee leer josephscott.org/archives/2010/01/php-count-performance. Básicamente, detalla cómo obtener la longitud de la matriz es o (1) y el impacto de las llamadas de función repetidas.
TheClair
1
¿Hacer una llamada a una función siempre es más lento que no hacer una? No me sorprendería encontrar que el intérprete tenga optimización en línea.
corsiKa
1
the count method of that object will be called, ¿podría explicar esto un poco
Steel Brain
1
@SteelBrain si una clase implementa la Countableinterfaz, entonces llamar count($object)es lo mismo que llamar $object->count(). Consulte 3v4l.org/oYSSC, por ejemplo.
mfonda
you're still making a function call when which is slower than not making oneEsta afirmación puede estar equivocada. Si está haciendo un recorrido manual, eso es O(n)operación. Pero si solo desea recuperar un valor precalculado, la operación es O(1).
Jamshad Ahmad