140 votes

Nombre, taille, longueur... trop de choix en Ruby ?

Je n'arrive pas à trouver de réponse définitive à ce sujet et je veux être sûr de bien comprendre ce qui se passe au "nième niveau" :-)

    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

Alors, lequel utiliser ? Si je veux savoir si a a plus d'un élément, cela ne semble pas avoir d'importance, mais je veux m'assurer que je comprends la vraie différence. Cela s'applique également aux tableaux. J'obtiens les mêmes résultats.

De plus, je réalise que count/size/length ont des significations différentes avec ActiveRecord. Pour l'instant, je suis surtout intéressé par le Ruby pur (1.92), mais si quelqu'un veut m'expliquer la différence entre AR et ActiveRecord, j'apprécierais également.

Merci !

194voto

Mark Byers Points 318575

Pour les tableaux et les hachages size est un alias pour length . Ce sont des synonymes et ils font exactement la même chose.

count est plus polyvalent - il peut prendre un élément ou un prédicat et ne compter que les éléments qui correspondent.

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

Dans le cas où vous Ne le fais pas. fournit un paramètre pour compter, cela a fondamentalement le même effet que d'appeler length. Il peut cependant y avoir une différence de performance.

On peut voir dans le code source pour Array qu'ils font presque exactement la même chose. Voici le code C pour l'implémentation de array.length :

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

Et voici la partie pertinente de l'implémentation 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..
    }
}

Le code pour array.count effectue quelques vérifications supplémentaires mais, au final, appelle exactement le même code : LONG2NUM(RARRAY_LEN(ary)) .

Les hachages ( code source ) d'autre part ne semblent pas implémenter leur propre version optimisée de count Ainsi, l'implémentation de Enumerable ( code source ) est utilisé, qui itère sur tous les éléments et les compte un par un.

En général, je conseille d'utiliser length (ou son alias size ) plutôt que count si vous voulez savoir combien d'éléments il y a en tout.


En ce qui concerne ActiveRecord, en revanche, il y a sont des différences importantes. consultez ce post :

10voto

stef Points 6478

Il existe une différence cruciale pour les applications qui utilisent des connexions à des bases de données.

Lorsque vous utilisez plusieurs ORM (ActiveRecord, DataMapper, etc.), il est généralement admis que .size génère une requête qui demande tous les éléments de la base de données ('select * from mytable') et vous donne ensuite le nombre d'éléments obtenus, alors que .count génère une requête unique ('select count(*) from mytable') qui est considérablement plus rapide.

Parce que ces ORMs sont si répandus, je suis le principe du moindre étonnement. En général, si j'ai déjà quelque chose en mémoire, alors j'utilise .size, et si mon code va générer une requête vers une base de données (ou un service externe via une API), j'utilise .count.

7voto

Dans la plupart des cas (par exemple Array o Chaîne de caractères ) size est un alias para length .

count vient normalement de Énumérable et peut prendre un bloc prédicat optionnel. Ainsi, enumerable.count {cond} est [approximativement] (enumerable.select {cond}).length -- il peut bien sûr contourner la structure intermédiaire puisqu'il n'a besoin que du nombre de prédicats correspondants.

Note : Je ne suis pas sûr que count forces une évaluation de l'énumération si le bloc n'est pas spécifié ou s'il est court-circuité à l'adresse suivante length si possible.

Edit (et merci à la réponse de Mark !): count sans bloc (au moins pour les Arrays) n'est pas forcer une évaluation. Je suppose que sans comportement formel, c'est "ouvert" pour d'autres implémentations, si forcer une évaluation sans prédicat n'a jamais vraiment de sens de toute façon.

5voto

profimedica Points 371

J'ai trouvé un bon logiciel à http://blog.hasmanythrough.com/2008/2/27/count-length-size

Dans ActiveRecord, il existe plusieurs façons de déterminer le nombre d'enregistrements d'une association. dans une association, et il y a quelques différences subtiles dans la façon dont ils fonctionnement.

post.comments.count - Déterminer le nombre d'éléments avec une requête SQL COUNT. Vous pouvez également spécifier des conditions pour ne compter qu'un sous-ensemble de sous-ensemble des éléments associés (par exemple, :conditions => {:author_name => "josh "josh"}). Si vous avez mis en place un cache de compteur sur l'association, #count retournera cette valeur en cache au lieu d'exécuter une nouvelle requête.

post.comments.length - Ceci charge toujours le contenu de la rubrique en mémoire, puis renvoie le nombre d'éléments chargés. Notez que cela ne forcera pas une mise à jour si l'association avait été précédemment chargée et que de nouveaux commentaires ont été créés par un autre moyen (ex. manière (par exemple, Comment.create(...) au lieu de post.comments.create(...)).

post.comments.size - Cette option est une combinaison des deux options précédentes. précédentes. Si la collection a déjà été chargée, elle retournera sa longueur comme si vous appeliez #length. Si la collection n'a pas encore été chargée, il s'agit de comme si vous appeliez #count.

J'ai aussi une expérience personnelle :

<%= h(params.size.to_s) %> # works_like_that !
<%= h(params.count.to_s) %> # does_not_work_like_that !

2voto

Venkat M Points 4281

Nous disposons de plusieurs méthodes pour déterminer le nombre d'éléments d'un tableau, par exemple .length , .count y .size . Cependant, il est préférable d'utiliser array.size plutôt que array.count . Parce que .size est plus performant.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X