Codementor Events

Python's Counter - Part 1

Published May 19, 2019Last updated May 30, 2019
Python's Counter - Part 1

Python is elegant! Everyone knows that - Well, Maybe.

Python has everything!...Oops! I know everyone will not agree.
But, let's see how much more we can disagree subsequently. Kindly take note that all code is Python 3.

If we had a list of names representing votes like below, let's find out who won.

votes = ['Giggs', 'Giggs', 'Greg', 'Joan', 'Jenny', 'Jenny', 'Jenny', 'Jones']

Without thinking hard about optimization or any other technicalities, we may approach it like this:

>>> # Lets get a dictionary containing the 
>>> # name of each contestant and their number of votes
>>>
>>> votes_dict = {}
>>>
>>> for contestant in votes:
...	if contestant in votes_dict:
...	    votes_dict[contestant] += 1
...	else:
...	    votes_dict[contestant] = 1
...
...

Our votes dictionary should look like this:

{'Giggs': 2, 'Greg': 1, 'Joan': 1, 'Jenny': 3, 'Jones': 1}

Now, we can get the winner by finding out the contestant with the highest vote count. We will sort the list of contestants and their number of votes.

>>> # sort contestants by their votes in descending order, 
>>> # into "contestant name, number of votes" tuples
>>>
>>> contestants_sorted = sorted(
...    votes_dict.items(), 
...    key=lambda contestant: contestant[1], 
...    reverse = True
... )

Our list of "contestant name, number of votes" tuples, in order of top votes to least votes, should look like this:

[('Jenny', 3), ('Giggs', 2), ('Greg', 1), ('Joan', 1), ('Jones', 1)]

Obviously, Jenny won. So let's display that programmatically.

>>> # Let's pick the name of the winner, and number of votes.
>>> # Obviously that is in the first tuple.
>>> # Then let's display them.
>>>
>>> winner, top_votes = contestants_sorted[0]
>>> print('{} won with {} votes.'.format(winner, top_votes))

Finally, the winner should be displayed like this:

 Jenny won with 3 votes.

A simpler way...

Can there be a more elegant, simpler way to do it?

That brings us to our first hidden tool called Counter.
It is part of python's in-built collections library. The Python Software Foundation defines it this way.

A Counter is a dict subclass for counting hashable objects. It is a collection where elements are stored as dictionary keys and their counts are stored as dictionary values. Counts are allowed to be any integer value including zero or negative counts. The Counter class is similar to bags or multisets in other languages.

In simple terms, we can say a Counter is like a dictionary, and stores key-value pairs. However, unlike the usual dictionary, its values are always numbers, representing the count of a given item, which is the key. As we use it subsequently, it should be easier to appreciate it.

So back to our votes, we can determine the winner in fewer lines of code using Counter.
Let's see below!

Once again, below is our list of votes:

>>> votes = ['Giggs', 'Giggs', 'Greg', 'Joan', 'Jenny', 'Jenny', 'Jenny', 'Jones']

We will import Counter to do the counting for us.

>>> from collections import Counter
>>>
>>> # let Counter count the votes
>>> votes_counter = Counter(votes)

This is what votes_counter contains; Each contestant and their number of vote.

Counter({'Jenny': 3, 'Giggs': 2, 'Greg': 1, 'Joan': 1, 'Jones': 1})

Clearly, Jenny won and we are on track. Let's get the winner's information

>>> #get winner using Counter's most_common() method.
>>> top_contestant_info = votes_counter.most_common(1)

Now, our top_contestant_info will contain this:

[('Jenny', 3)]

The most_common() method of Counter returns a list, with a number of tuples depending on the number we specify as a parameter. If you need the top 3 contestants, most_common(3) will return a list of three tuples representing the three topmost items.

For this illustration, we only wanted the top contestant and so we specified 1. We are assuming, and know there was no tie. In the real world, however, we would have to add extra code to deal with ties, but that is reserved for a more advanced post.

Now let's display the winner in a human way šŸ˜ƒ

>>> # let's get winner and winner votes
>>> # and display them
>>>
>>> winner, top_votes = top_contestant_info[0]
>>> print('{} won with {} votes.'.format(winner, top_votes))

And here is our winner:

Jenny won with 3 votes.

Counter couldn't have made life easier!!!

A recap of the two approaches:

Here's the votes' list:

>>> votes = [
...    'Giggs', 'Giggs', 'Greg', 
...	   'Joan', 'Jenny', 'Jenny', 
...	   'Jenny', 'Jones'
... ]
...
...

Approach 1.

>>> votes_dict = {}
>>>
>>> for contestant in votes:
...	if contestant in votes_dict:
...	    votes_dict[contestant] += 1
...	else:
...	    votes_dict[contestant] = 1
...
...
>>> contestants_sorted = sorted(
...     votes_dict.items(), 
...     key=lambda contestant: contestant[1], 
...     reverse = True
... )
...
...
>>> winner, top_votes = contestants_sorted[0]
>>> print('{} won with {} votes.'.format(winner, top_votes))
Jenny won with 3 votes.

Approach 2 - Using Counter

>>> from collections import Counter
>>>
>>> top_contestant_info = Counter(votes).most_common(1)
>>>
>>> winner, top_votes = top_contestant_info[0]
>>> print('{} won with {} votes.'.format(winner, top_votes))
Jenny won with 3 votes.

So there we go! Choose between the Counter and another way....
If you choose the Counter way, do well to read more from the Python Software Foundation here. You can also read Python's Counter - Part 2 here.

Discover and read more posts from Victor Ayi
get started
post comments2Replies
Nagesh K S
6 years ago

Hi Victor, Thanks for explaining the Counter concept. Actually Iā€™m new to Python and started learning it very recently.

Victor Ayi
6 years ago

Hello Nagesh, I am glad my article is helpful. :).