Nombre, taille, longueur… trop de choix dans Ruby?

Je n’arrive pas à trouver une réponse définitive à ce sujet et je veux m’assurer que je comprends cela au “nième niveau” 🙂


     a = {"a" => "Bonjour", "b" => "Monde"}
     a.count # 2
     a.size # 2
     a.longueur # 2

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

Alors, qui 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 de bien comprendre la différence. Cela s’applique également aux tableaux. J’ai les mêmes résultats.

De plus, je me rends compte que le nombre / la taille / la longueur ont des significations différentes avec ActiveRecord. Je suis surtout intéressé par Ruby pur (1.92) en ce moment, mais si quelqu’un veut marquer la différence, cela serait également apprécié.

Merci!

Pour les tableaux et les hachages, la size est un alias de length . Ce sont des synonymes et 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 correspondants.

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

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

Nous pouvons voir dans 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 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 de array.count effectue quelques vérifications supplémentaires mais finit par appeler le même code: LONG2NUM(RARRAY_LEN(ary)) .

Les hachages ( code source ), par contre, ne semblent pas implémenter leur propre version optimisée de count sorte que l’implémentation de Enumerable ( code source ) est utilisée, qui parcourt tous les éléments et les compte un par un.

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


En ce qui concerne ActiveRecord, en revanche, il existe des différences importantes. Découvrez ce post:

  • Compter les associations ActiveRecord: nombre, taille ou longueur?

Il existe une différence cruciale pour les applications qui utilisent des connexions de firebase database.

Lorsque vous utilisez de nombreux 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 firebase database (“select * from mytable”) et vous donnera ensuite 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 si répandus que je suis le principe de la moindre surprise. En général, si j’ai déjà quelque chose en mémoire, j’utilise la taille. Si mon code génère une requête vers une firebase database (ou un service externe via une API), j’utilise .count.

Dans la plupart des cas (par exemple, Array ou Ssortingng ), la size est un alias de length .

count vient normalement de Enumerable et peut prendre un bloc de prédicat optionnel. Ainsi, enumerable.count {cond} est [en gros] (enumerable.select {cond}).length – il est bien sûr possible de contourner la structure intermédiaire, car il suffit de compter le nombre de prédicats correspondants.

Note: Je ne suis pas sûr si count force 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 les tableaux) ne force pas l’évaluation. Je suppose que sans comportement formel, il est “ouvert” pour les autres implémentations, si forcer une évaluation sans prédicat ait même un sens.

J’ai trouvé une bonne réponse à http://blog.hasmanythrough.com/2008/2/27/count-length-size

Dans ActiveRecord, il existe plusieurs manières de déterminer combien d’enregistrements se trouvent dans une association et il existe des différences subtiles 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 compter uniquement un sous-ensemble des éléments associés (par exemple: conditions => {: author_name => “josh”}). Si vous configurez un cache de compteur sur l’association, #count retournera cette valeur mise en cache au lieu d’exécuter une nouvelle requête.

post.comments.length – Cela charge toujours le contenu de l’association en mémoire, puis retourne le nombre d’éléments chargés. Notez que cela ne forcera pas la mise à jour si l’association a déjà été chargée et que les nouveaux commentaires ont été créés d’une autre manière (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 appeler #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 ! 

Nous disposons de plusieurs méthodes pour déterminer le nombre d’éléments dans un tableau, tels que .length , .count et .size . Cependant, il est préférable d’utiliser array.size plutôt que array.count . Parce que la .size est meilleure en performance.

Ajout de 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 ces deux méthodes. Peut-être que vous ne verrez aucune différence de performance. Cependant, le array.count é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

Array # count n # Renvoie le nombre d’éléments ayant la valeur n dans Array

Array # count {| i | i.even?} Retourne le nombre en fonction de 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 avec la valeur 2

 array.count 2 # => 3 

Le tableau comporte trois éléments dont la valeur est 2.

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

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

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

J’espère que cela donne quelques informations sur la méthode de count .