count vs length vs size

 

In Ruby, #length and #size are synonyms and both do the same thing: they tell you how many elements are in an array or hash. Technically #length is the method and #size is an alias to it.

In ActiveRecord, there are several ways to find out how many records are in an association, and there are some subtle differences in how they work.

  • post.comments.count - Determine the number of elements with an SQL COUNT query. You can also specify conditions to count only a subset of the associated elements (e.g.:conditions => {:author_name => "josh"}). If you set up a counter cache on the association, #count will return that cached value instead of executing a new query.
  • post.comments.length - This always loads the contents of the association into memory, then returns the number of elements loaded. Note that this won't force an update if the association had been previously loaded and then new comments were created through another way (e.g.Comment.create(...)instead ofpost.comments.create(...)).
  • post.comments.size - This works as a combination of the two previous options. If the collection has already been loaded, it will return its length just like calling #length. If it hasn't been loaded yet, it's like calling #count.
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

For arrays and hashessizeis an alias forlength. They are synonyms and do exactly the same thing.

countis more versatile - it can take an element or predicate and count only those items that match.

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

In the case where youdon'tprovide a parameter to count it has basically the same effect as calling length. There can be a performance difference though.

We can see from thesource code for Arraythat they do almost exactly the same thing. Here is the C code for the implementation ofarray.length:

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

And here is the relevant part from the implementation ofarray.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.. } } 

The code forarray.countdoes a few extra checks but in the end calls the exact same code:LONG2NUM(RARRAY_LEN(ary)).

Hashes (source code) on the other hand don't seem to implement their own optimized version ofcountso the implementation fromEnumerable(source code) is used, which iterates over all the elements and counts them one-by-one.

In general I'd advise usinglength(or its aliassize) rather thancountif you want to know how many elements there are altogether.


你可能感兴趣的:(Ruby)