
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.)

Welcome to the third installment in Joey’s Unofficial RubyFringe Guide to Toronto, a series of offbeat articles to acquaint attendees of the upcoming 














