The Elements of Style in Ruby #13: length vs size vs count
One of the problems newcomers to Ruby experience is that there are
often quite a few ways to do same thing. For instance - you can obtain
the number of items in Enumerable
objects (instances of classes
using the Enumerable
mixin, which would often be collections like
Array
, Hash
, Set
, etc) by either using Enumerable#count
or the
methods length
and its alias size
that such classes often
provide.
arr = [1, 2, 3]
arr.length # => 3
arr.size # => 3
arr.count # => 3
h = { a: 1, b: 2 }
h.length # => 2
h.size # => 2
h.count # => 2
str = 'name'
str.length # => 4
str.size # => 4
# str.count won't work as String does not include Enumerable
Which one should you use? Let me help with this choice.
length
is a method that’s not part of Enumerable
- it’s part of a
concrete class (like String
or Array
) and it’s usually running in
O(1)
(constant) time. That’s as fast as it gets, which means that
using it is probably a good idea.
Whether you should use length
or size
is mostly a matter of
personal preference. Personally I use size
for collections (hashes,
arrays, etc) and length
for strings, since for me objects like
hashes and stacks don’t have a length, but a size (defined in terms of
the elements they contain). Conversely, it’s perfectly normal to
assume that some text has some length. Anyways, in the end you’re
invoking the same method, so the semantic distinction is not
important.
Enumerable#count
, on the other hand, is a totally different
beast. It’s usually meant to be used with a block or an argument and
will return the number of matches in an Enumerable
:
arr = [1, 1, 2, 3, 5, 6, 8]
arr.count(&:even?) # => 3
arr.count(1) # => 2
You can, however, invoke it without any arguments and it will return the size of the enumerable on which it was invoked:
arr.count # => 7
There’s a performance implication with this, though - to calculate the
size of the enumerable the count
method will traverse it, which is
not particularly fast (especially for huge collections). Some classes
(like Array
) implement an optimized version of count
in terms of
length
, but many don’t.
The takeaway for you is that you should
avoid using the count
method if you can use length
or size
.
A note to Rails developers - ActiveRecord::Relation
’s length
,
size
and count
methods have a totally different meaning, but that’s
irrelevant to our current discussion.
That’s all for now, folks! As usual I’m looking forward to hearing your thoughts here and on Twitter!