Cuenta, tamaño, longitud too ¿demasiadas opciones en Ruby?


Parece que no puedo encontrar una respuesta definitiva sobre esto y quiero asegurarme de entender esto al "n'ésimo nivel": -)


    a = { "a" => "Hello", "b" => "World" }
    a.count  # 2
    a.size   # 2
    a.length # 2

    a = [ 10, 20 ]
    a.count  # 2
    a.size   # 2
    a.length # 2

Entonces, ¿cuál usar? Si quiero saber si a tiene más de un elemento, entonces no parece importar, pero quiero asegurarme de entender la verdadera diferencia. Esto también se aplica a los arrays. Obtengo los mismos resultados.

Además, me doy cuenta de que count/size/length tienen diferentes significados con ActiveRecord. Estoy principalmente interesado en pure Ruby (1.92) en este momento pero si alguien quiere intervenir en la diferencia AR hace que sería apreciado también.

Gracias!

Author: Noha Kareem, 2010-12-29

6 answers

Para arrays y hashes size es un alias para length. Son sinónimos y hacen exactamente lo mismo.

count es más versátil: puede tomar un elemento o predicado y contar solo aquellos elementos que coincidan.

> [1,2,3].count{|x| x > 2 }
=> 1

En el caso en que no proporcione un parámetro para contar, tiene básicamente el mismo efecto que llamar a length. Sin embargo, puede haber una diferencia de rendimiento.

Podemos ver en la fuente código para Array que hacen casi exactamente lo mismo. Aquí está el código C para la implementación de array.length:

static VALUE
rb_ary_length(VALUE ary)
{
    long len = RARRAY_LEN(ary);
    return LONG2NUM(len);
}

Y aquí está la parte relevante de la implementación de array.count:

static VALUE
rb_ary_count(int argc, VALUE *argv, VALUE ary)
{
    long n = 0;

    if (argc == 0) {
        VALUE *p, *pend;

        if (!rb_block_given_p())
            return LONG2NUM(RARRAY_LEN(ary));

        // etc..
    }
}

El código para array.count hace algunas comprobaciones adicionales, pero al final llama exactamente al mismo código: LONG2NUM(RARRAY_LEN(ary)).

Hashes (código fuente) en el otro lado, no parecen implementar su propia versión optimizada de count por lo que la implementación de Enumerable (código fuente) se utiliza, que itera sobre todos los elementos y los cuenta uno por uno.

En general, aconsejaría usar length (o su alias size) en lugar de count si desea saber cuántos elementos hay en conjunto.


En cuanto a ActiveRecord, por otro lado, hay diferencias importantes. echa un vistazo a esta publicación:

 187
Author: Mark Byers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-05 11:28:33

Hay una diferencia crucial para las aplicaciones que hacen uso de conexiones de base de datos.

Cuando está utilizando muchosMs (ActiveRecord, DataMapper, etc.) el entendimiento general es que .size generará una consulta que solicita todos los elementos de la base de datos ('select * from mytable') y luego le dará el número de elementos resultantes, mientras que .count generará una única consulta ('select count(*) from mytable') que es considerablemente más rápida.

Porque estosMs son tan prevalente I siguiendo el principio del menor asombro. En general, si tengo algo en la memoria ya, entonces uso .tamaño, y si mi código va a generar una solicitud a una base de datos (o servicio externo a través de una API) utilizo .contar.

 10
Author: stef,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-12-29 08:00:44

En la mayoría de los casos (por ejemplo, Array o String) size es un alias para length.

count normalmente viene de Enumerable y puede tomar un bloque de predicados opcional. Por lo tanto enumerable.count {cond} es [aproximadamente] (enumerable.select {cond}).length can por supuesto, puede omitir la estructura intermedia, ya que solo necesita el recuento de predicados coincidentes.

Nota: No estoy seguro si count fuerza una evaluación de la enumeración si el bloque no está especificado o si cortocircuita para el length si es posible.

Editar (y gracias a la respuesta de Mark!): count sin un bloque (al menos para matrices) no fuerza una evaluación. Supongo que sin un comportamiento formal es "abierto" para otras implementaciones, si forzar una evaluación sin un predicado realmente tiene sentido de todos modos.

 7
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-12-29 02:04:00

Encontré un buen answare en http://blog.hasmanythrough.com/2008/2/27/count-length-size

En ActiveRecord, hay varias maneras de averiguar cuántos registros están en una asociación, y hay algunas diferencias sutiles en cómo funcionan.

Post.comentario.count-Determinar el número de elementos con un SQL Consulta de recuento. También puede especificar condiciones para contar solo un subconjunto de los elementos asociados (por ejemplo,: conditions => {:author_name => "josh"}). Si configura una caché de contador en la asociación, #count devolverá ese valor en caché en lugar de ejecutar una nueva consulta.

Post.comentario.longitud - Esto siempre carga el contenido de la asociación en memoria, luego devuelve el número de elementos cargados. Tenga en cuenta que esto no forzará una actualización si la asociación previamente cargado y luego nuevos comentarios fueron creados a través de otro camino (por ejemplo, Comentario.crear(...) en lugar de post.comentario.crear(...)).

Post.comentario.tamaño-Esto funciona como una combinación de los dos anteriores opcion. Si la colección ya se ha cargado, devolverá su length al igual que llamando # length. Si aún no se ha cargado, es como llamar a # count.

También tengo una experiencia personal:

<%= h(params.size.to_s) %> # works_like_that !
<%= h(params.count.to_s) %> # does_not_work_like_that !
 5
Author: profimedica,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-20 00:37:57

Tenemos varias maneras de averiguar cuántos elementos en una matriz como .length, .count y .size. Sin embargo, Es mejor usar array.size en lugar de array.count. Porque .size es mejor en rendimiento.

 2
Author: Venkat M,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-06 13:02:14

Añadiendo más a la respuesta de Mark Byers. En Ruby el método array.sizees un alias al método Array#length. No hay diferencia técnica en el uso de cualquiera de estos dos métodos. Posiblemente no verá ninguna diferencia en el rendimiento también. Sin embargo, el array.count también hace el mismo trabajo pero con algunas funcionalidades adicionales Array # count

Se puede usar para obtener el número total de elementos basados en alguna condición. Count se puede llamar de tres maneras:

Array # count # Devuelve el número de elementos en el Array

Array # count n # Devuelve el número de elementos que tienen valor n en Array

Array # count {/i / i. even?} Devuelve el recuento basado en la condición invocada en cada matriz de elementos

array = [1,2,3,4,5,6,7,4,3,2,4,5,6,7,1,2,4]

array.size     # => 17
array.length   # => 17
array.count    # => 17

Aquí los tres métodos hacen el mismo trabajo. Sin embargo aquí es donde el count se pone interesante.

Digamos, quiero encontrar cuántos elementos de matriz contiene la matriz con valor 2

array.count 2    # => 3

La matriz tiene un total de tres elementos con valor como 2.

Ahora, quiero encontrar todos los elementos de matriz mayores que 4

array.count{|i| i > 4}   # =>6

La matriz tiene un total de 6 elementos que son > que 4.

Espero que dé algo de información sobre el método count.

 1
Author: Prabhakar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-15 06:07:04