web-dev-qa-db-fra.com

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

Je n'arrive pas à trouver une réponse définitive à ce sujet et je veux m'assurer de bien comprendre cela au "nième niveau" :-)

 
 a = {"a" => "Bonjour", "b" => "Monde"} 
 a.compte # 2 
 a.size # 2 
 A.Longueur # 2 
 
 A = [10, 20] 
 A.count # 2 
 A.size # 2 
 a.longueur # 2 
 

Alors, lequel utiliser? Si je veux savoir si a comporte plus d'un élément, alors cela ne semble pas avoir d'importance, mais je veux m'assurer de bien comprendre la différence. Cela s’applique aussi aux tableaux. J'ai les mêmes résultats.

De plus, je réalise que compte/taille/longueur a différentes significations avec ActiveRecord. Je suis surtout intéressé par pure Ruby (1,92) pour le moment, mais si quelqu'un veut commenter la différence que fait AR, cela serait également apprécié.

Merci!

138
cbmeeks

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

count est plus polyvalent - il peut prendre un élément ou un prédicat et compter uniquement les éléments correspondants.

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

Dans le cas où vous ne fournissez pas un paramètre à compter, cela a essentiellement le même effet que la longueur de l'appel. Cependant, il peut y avoir une différence de performance.

Nous pouvons voir d'après le code source de 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 la mise en œuvre 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 appelle finalement 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, donc l’implémentation de Enumerable ( code source ) est utilisé, qui parcourt tous les éléments et les compte un par un.

En général, je vous conseillerais d'utiliser length (ou son alias size) plutôt que count si vous voulez savoir le nombre total d'éléments.


En ce qui concerne ActiveRecord, par contre, il y a des différences importantes. Découvrez ce post:

192
Mark Byers

Il y a une différence cruciale pour les applications qui utilisent des connexions de base de données.

Lorsque vous utilisez plusieurs ORM (ActiveRecord, DataMapper, etc.), il est généralement admis que .size générera une requête qui demande tous les éléments de la base de données ('select * from mytable'), puis vous indique le nombre d'éléments. résultant, alors que .count générera une seule requête ('select count (*) from mytable') qui est considérablement plus rapide.

Parce que ces ORM sont tellement répandus, je respecte le principe du moindre étonnement. En général, si j'ai déjà quelque chose en mémoire, j'utilise .size. 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.

10
stef

Dans la plupart des cas (par exemple, Tablea ou Chaîne ) size est un alias pour length.

count provient normalement de Enumerable et peut prendre un bloc de prédicat facultatif. Ainsi enumerable.count {cond} est [approximativement] (enumerable.select {cond}).length - il peut bien sûr contourner la structure intermédiaire car il ne nécessite que le nombre de prédicats correspondants.

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

Edit (et grâce à la réponse de Mark!): count sans bloc (au moins pour Tableaux) ne le fait pas forcer une évaluation. Je suppose que sans comportement formel, il est "ouvert" pour d'autres implémentations, même si forcer une évaluation sans prédicat a toujours un sens.

7
user166390

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

Dans ActiveRecord, il existe plusieurs manières de connaître le nombre d'enregistrements dans une association, et il existe de subtiles différences dans leur fonctionnement.

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

post.comments.length - Ceci charge toujours le contenu de l'association en mémoire, puis renvoie le nombre d'éléments chargés. Notez que cela ne force pas la mise à jour si l'association a déjà été chargée et que de nouveaux commentaires sont ensuite créés (par exemple, Comment.create (...) au lieu de post.comments.create (...)).

post.comments.size - Cela fonctionne comme une combinaison des deux options précédentes. Si la collection a déjà été chargée, elle retournera sa longueur comme si vous appeliez #length. S'il n'a pas encore été chargé, c'est 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 !
5
profimedica

Nous avons plusieurs façons de savoir combien d'éléments d'un tableau comme .length, .count et .size. Cependant, il vaut mieux utiliser array.size plutôt que array.count. Car .size est meilleur en performance.

2
Venkat M

Ajouter plus à la réponse de Mark Byers. Dans Ruby la méthode array.size est un alias de la méthode Array # length . Il n'y a pas de différence technique dans l'utilisation de l'une de ces deux méthodes. Peut-être que vous ne verrez pas non plus de différence dans les performances. Cependant, le array.count fait également le même travail mais avec quelques fonctionnalités supplémentaires Array # count

Il peut être utilisé pour obtenir le nombre total d'éléments en fonction de certaines conditions. Count peut être appelé de trois manières:

Array # count # Renvoie le nombre d'éléments dans Array.

Tableau # nombre n # Renvoie le nombre d'éléments ayant la valeur n dans Tableau.

Nombre de tableaux {| i | i.even?} Retourne le nombre basé sur la condition invoquée sur chaque tableau d'éléments

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

Ici, les trois méthodes font le même travail. Cependant, voici où le count devient intéressant.

Disons, je veux trouver combien d'éléments de tableau le tableau contient-il avec une valeur 2

array.count 2    # => 3

Le tableau a un total de trois éléments dont la valeur est 2.

Maintenant, je veux trouver tous les éléments de tableau supérieurs à 4

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

Le tableau a un total de 6 éléments qui sont> que 4.

J'espère que cela donne des informations sur la méthode count.

1
Prabhakar