Multisets, `collections.Counter`
Topics: Multisets, collections.Counter
Counting objects
Today I want to present a very useful class in Python: collections.Counter
. You might wonder what is so great about this class: it allows us to count all kinds of objects! And who doesn’t love counting? For example, consider all the potion ingredients Cleon, Flynn and Cassidy need to buy for a school year. We can easily create a shopping list for them using collections.Counter
.
What is collections.Counter
?
The Counter
class is a dictionary subclass. To be more precise, a Counter is an unordered collection of elements, where the elements are stored as dictionary keys and their counts as dictionary values.
Because a Counter is a kind of dictionary, the stored elements must be hashable. In Python, all immutable objects (like strings) are hashable, while mutable objects (like lists) are not hashable (remember: immutable means that once we created an object, we can’t change it anymore).
The definition of hashable states that “an object is hashable if it has a hash value which never changes during its lifetime (it needs a hash() method), and can be compared to other objects (it needs an eq() method)”.
Creating a shopping list
Let’s see how we can create a shopping list and count all potion ingredients we need to buy.
from collections import Counter
from magical_universe import Potion
# Step 1: Create the potions
flask_of_remembrance = Potion(['raven eggshells', 'tincture of thyme', 'unicorn tears',
'dried onions', 'powdered ginger root'])
vial_of_anger = Potion(['dried dragon skin', 'leeches', 'shredded elephant tusk',
'horned flies', 'earthworm juice', 'dried onions'])
ancient_wisdom = Potion(['tincture of thyme', 'leeches', 'drakus flower', 'lavender sprig',
'earthworm juice', 'cactus juice', 'dried onions'])
brew_of_lies = Potion(['horned flies', 'leeches', 'drakus flower', 'horned flies',
'unicorn tears', 'cactus juice'])
# Step 2: Create list of all potions
all_potions = [flask_of_remembrance, vial_of_anger, ancient_wisdom, brew_of_lies]
# Step 3: Create the shopping list!
shopping_list = Counter()
for potion in all_potions:
for ingredient in potion:
shopping_list[ingredient] += 1
print(f"Final shopping list: {shopping_list}")
Further reading
The collections.Counter
class has a few useful methods, for example, Counter.most_common()
. To learn more about the Counter class, look at the Python docs.