
Welcome to the fourth installment of Enumerating Enumerable, a series of articles in which I challenge myself to do a better job of documenting Ruby’s Enumerable module than RubyDoc.org does. In this article, I’ll cover Enumerable#count, one of the new methods added to Enumerable in Ruby 1.9.
In case you missed the earlier installments, they’re listed (and linked) below:
Enumerable#count Quick Summary

| In the simplest possible terms | How many items in the collection meet the given criteria? |
|---|---|
| Ruby version | 1.9 only |
| Expects | Either:
|
| Returns | The number of items in the collection that meet the given criteria. |
| RubyDoc.org’s entry | Enumerable#count |
Enumerable#count and Arrays
When used on an array and an argument is provided, count returns the number of times the value of the argument appears in the array:
# How many instances of "zoom" are there in the array?
["zoom", "schwartz", "profigliano", "zoom"].count("zoom")
=> 2
# Prior to Ruby 1.9, you'd have to use this equivalent code:
["zoom", "schwartz", "profigliano", "zoom"].select {|word| word == "zoom"}.size
=> 2
When used on an array and a block is provided, count returns the number of items in the array for which the block returns true:
# How many members of "The Mosquitoes" (a Beatles-esque band that appeared on
# "Gilligan's Island") have names following the "B*ngo" format?
["Bingo", "Bango", "Bongo", "Irving"].count {|bandmate| bandmate =~ /B[a-z]ngo/}
=> 3
# Prior to Ruby 1.9, you'd have to use this equivalent code:
["Bingo", "Bango", "Bongo", "Irving"].select {|bandmate| bandmate =~ /B[a-z]ngo/}.size
RubyDoc.org says that when count is used on an array without an argument or a block, it simply returns the number of items in the array (which is what the length/size methods do). However, when I’ve tried it in irb and ruby, I got results like this:
[1, 2, 3, 4].count => #<Enumerable::Enumerator:0x189d784>
Enumerable#count and Hashes
As with arrays, when used on a hash and an argument is provided, count returns the number of times the value of the argument appears in the hash. The difference is that for the comparison, each key/value pair is treated as a two-element array, with the key being element 0 and the value being element 1.
# Here's a hash where the names of recent movies are keys
# and their metacritic.com ratings are the corresponding values.
movie_ratings = {"Get Smart" => 53, "Kung Fu Panda" => 88, "The Love Guru" => 15,
"Sex and the City" => 51, "Iron Man" => 93}
=> {"Get Smart"=>53, "Kung Fu Panda"=>88, "The Love Guru"=>15, "Sex and the City"=>51, "Iron Man"=>93}
# This statement will return a count of 0, since there is no item in movie_ratings
# that's just plain "Iron Man".
movie_ratings.count("Iron Man")
=> 0
# This statement will return a count of 1, since there is an item in movie_ratings
# with the key "Iron Man" and the corresponding value 93.
movie_ratings.count(["Iron Man", 93])
=> 1
# This statement will return a count of 0. There's an item in movie_ratings
# with the key "Iron Man", but its corresponding value is NOT 92.
movie_ratings.count(["Iron Man", 92])
=> 0
count is not useful when used with a hash and an argument. It will only ever return two values:
1if the argument is a two-element array and there is an item in the hash whose key matches element [0] of the array and whose value matches element [1] of the array.0for all other cases.
When used with a hash and a block, count is more useful. count passes each key/value pair in the hash to the block, which you can “catch” as either:
- A two-element array, with the key as element 0 and its corresponding value as element 1, or
- Two separate items, with the key as the first item and its corresponding value as the second item.
Each key/value pair is passed to the block and count returns the number of items in the hash for which the block returns true.
# Once again, a hash where the names of recent movies are keys
# and their metacritic.com ratings are the corresponding values.
movie_ratings = {"Get Smart" => 53, "Kung Fu Panda" => 88, "The Love Guru" => 15,
"Sex and the City" => 51, "Iron Man" => 93}
=> {"Get Smart"=>53, "Kung Fu Panda"=>88, "The Love Guru"=>15, "Sex and the City"=>51, "Iron Man"=>93}
# How many movie titles in the collection start
# in the first half of the alphabet?
# (Using a one-parameter block)
movie_ratings.count {|movie| movie[0] <= "M"}
=> 3
# How many movie titles in the collection start
# in the first half of the alphabet?
# (This time using a two-parameter block)
movie_ratings.count {|title, rating| title <= "M"}
=> 3
# Here's how you'd do it in pre-1.9 Ruby:
movie_ratings.select {|movie| movie[0] <= "M"}.size
=> 3
# or...
movie_ratings.select {|title, rating| title <= "M"}.size
=> 3
# How many movies in the collection had a rating
# higher than 80?
# (Using a one-parameter block)
movie_ratings.count {|movie| movie[1] > 80}
=> 2
# How many movies in the collection had a rating
# higher than 80?
# (This time using a two-parameter block)
movie_ratings.count {|title, rating| rating > 80}
=> 2
# Here's how you'd do it in pre-1.9 Ruby:
movie_ratings.select {|title, rating| rating > 80}.size
=> 2
# How many movies in the collection have both:
# - A title starting in the second half of the alphabet?
# - A rating less than 50?
# (Using a one-parameter block)
movie_ratings.count {|movie| movie[0] >= "M" && movie[1] < 50}
=> 1
# How many movies in the collection have both:
# - A title starting in the second half of the alphabet?
# - A rating less than 50?
# (This time using a two-parameter block)
movie_ratings.count {|title, rating| title >= "M" && rating < 50}
=> 1
# Here's how you'd do it in pre-1.9 Ruby:
movie_ratings.select {|title, rating| title >= "M" && rating < 50}.size
=> 1
(You should probably skip The Love Guru completely, or at least until it gets aired on TV for free.)
5 replies on “Enumerating Enumerable: Enumerable#count”
[…] count […]
[…] count […]
[…] count […]
[…] count […]
[…] count […]