In Progress
Unit 1, Lesson 1
In Progress

Count

Video transcript & code

Well, it's time once again for a class president to be elected. The speeches have been given, skits performed, and all that remains is to tally up the votes.

We have a collection of votes as a hash mapping students to the candidate they voted for.

VOTES = {
  "Napoleon" => "Pedro",
  "Don"      => "Summer",
  "Deb"      => "Pedro",
  "Randy"    => "Summer",
  "Trisha"   => "Pedro",
}

For the purposes of tallying, we don't need the whole hash. We just need the values.

VOTES.values
# => ["Pedro", "Summer", "Pedro", "Summer", "Pedro"]

First off, let's get the total number of votes cast. If you've been using Ruby for a while, you probably know that we have several options for getting the number of items in a collection.

There is both #size, and #length. The one we use is purely a matter of personal preference.

But there is also #count, which at first glance appears to be yet another redundant method. But as we will see momentarily, #count isn't as superfluous as it may at first appear.

require "./votes"

VOTES.values.size               # => 5
VOTES.values.length             # => 5
VOTES.values.count              # => 5

Now that we have our total count, let's see how many votes were cast for Pedro. In order to narrow the collection to just the votes for Pedro, we can use #select with a block that matches the name "Pedro".

Then we can find the size of the resulting subset, and we have our vote count.

require "./votes"

VOTES.values.select{|v| v == "Pedro"}
# => ["Pedro", "Pedro", "Pedro"]

VOTES.values.select{|v| v == "Pedro"}.size
# => 3

It feels a bit weird, though, to produce this intermediate collection of identical strings just so we can count them. This situation is where the #count method comes into its own.

Instead of select, we can send the #count message directly to the whole collection. And we can give the same block we gave to #select to #count instead.

require "./votes"

VOTES.values.count{|v| v == "Pedro"}
# => 3

The result is a count of votes for Pedro. This time, there was no need to build a temporary collection of votes just so that we could count them.

This version is shorter and more efficient. But #count isn't quite out of tricks yet. It turns out that for cases like this one, #count has an even more concise form. We can pass in a value as an argument, and #count will tally up only the objects which are equivalent to the given value. This equivalency is determined using double-equals (==) comparison.

require "./votes"

VOTES.values.count("Pedro")
# => 3

Not only is this the shortest version yet, I think it reads beautifully as well.

And that's it for today. Happy hacking!

Responses