Python
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax and Data Types
-
Section 3: Collections
-
39: Set Operations: Union, Intersection, Difference
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Turtle Graphics and Early Practice Projects
-
Section 7: Working with Files and I/O
-
Section 8: Regular Expressions
-
Section 9: Object-Oriented Python
-
Section 10: Error Handling
-
Section 11: Modules and Packages
-
Section 12: Iterators, Generators, and Functional Tools
-
Section 13: Decorators and Metaprogramming
-
Section 14: Concurrency and Parallelism
-
Section 15: Working with Dates, Times, and Numbers
-
Section 16: Standard Library Deep Dive I: Data Structures
-
Section 17: Standard Library Deep Dive II: System and Introspection
-
Section 18: Standard Library Deep Dive III: Security and Encoding
-
Section 19: Standard Library Deep Dive IV: Text and Data Utilities
-
Section 20: Networking and Web Basics
-
Section 21: Working with Databases
-
Section 22: Testing and Quality
-
Section 23: Advanced Typing
-
Section 24: Context Managers and Resource Handling
-
Section 25: Text, Unicode, and Binary Data
-
Section 26: More Functional and Iteration Tools
-
Section 27: Data Validation and Configuration
-
Section 28: Working with Images and Media
-
Section 29: Property-Based and Documentation Testing
-
Section 30: Packaging and Deployment
-
Section 31: Performance and Internals
-
Section 32: Design Patterns in Python
-
Section 33: GUI Programming
-
Section 34: Security Basics
-
Section 35: Data Structures and Algorithms
-
Section 36: Practical Projects
-
Section 37: Capstone Projects
-
Section 38: Interview and Algorithm Practice
-
Section 39: Writing Idiomatic Python
229: Collections Module: Counter
You've probably used a dictionary to count things before. The pattern is always the same: check if the key exists, if not, initialize it to zero, then increment. It works, but it's tedious boilerplate. That's why I almost always reach for collections.Counter when I need to tally items.
Let's build something practical. Imagine we're writing a small tool for a game to analyze "loot drops" from a monster. We want to know exactly how many of each item dropped over a series of runs to see if the drop rates feel balanced.
Tallying the loot drops
First, I'll start with a raw list of items. In a real scenario, this might come from a CSV or a database, but for now, a simple list will do.
from collections import Counter
loot_drops = [
"Rusty Sword", "Health Potion", "Gold Coin", "Gold Coin",
"Health Potion", "Gold Coin", "Iron Shield", "Gold Coin",
"Health Potion", "Mana Potion", "Gold Coin"
]
# Instead of a for-loop and a dict, I just pass the list straight in
inventory = Counter(loot_drops)
print(inventory)
# Output: Counter({'Gold Coin': 5, 'Health Potion': 3, 'Mana Potion': 1, 'Iron Shield': 1, 'Rusty Sword': 1})
The Counter object is actually a subclass of a dictionary, so it behaves like one, but it's specialized for counting. The magic here is that I didn't have to write a single if key not in dict statement.
Finding the most common items
Usually, we don't just want the whole list; we want the "top X" items. This is where most_common() comes in. I'll use it to find the two most frequent drops.
top_two = inventory.most_common(2)
print(top_two)
# Output: [('Gold Coin', 5), ('Health Potion', 3)]
Now, here is where I often trip up when I'm coding quickly. I remember a time when I tried to access the count of the top item by treating the result of most_common() like a dictionary. I wrote something like top_two['Gold Coin'] and got a TypeError.
The mistake is forgetting that most_common() returns a list of tuples, not a dictionary. If you want to work with those results, you have to iterate through them or use index offsets:
# The wrong way: top_two['Gold Coin'] -> TypeError
# The right way:
for item, count in top_two:
print(f"The {item} dropped {count} times.")
Updating and subtracting counts
One of the most powerful things about Counter that people overlook is that you can perform mathematical operations on them. Let's say the player uses some items. Instead of manually decrementing values, I can create a second Counter for "consumed" items and subtract it from the first.
# Items the player used
consumed = Counter(["Gold Coin", "Gold Coin", "Health Potion"])
# Subtracting one counter from another
remaining_loot = inventory - consumed
print(remaining_loot)
# Output: Counter({'Gold Coin': 3, 'Health Potion': 2, 'Mana Potion': 1, 'Iron Shield': 1, 'Rusty Sword': 1})
I love this because it keeps the logic clean. I don't have to worry about whether a count drops below zero; Counter subtraction automatically removes keys with a result of zero or less, keeping the data tidy.
📋 Practical Task
Analyze Server Log Status Codes
You have been given a list of HTTP status codes captured from a server log. Your task is to use the Counter class to analyze the traffic.
logs = ["200", "404", "500", "200", "200", "404", "200", "500", "500", "500", "200", "403", "200"]
Write a script that does the following:
- Creates a
Counterobject to tally the status codes. - Prints the total number of "200" (Success) responses.
- Prints the single most common status code and its count.
- Creates a second Counter representing "resolved" issues:
{"500": 2, "404": 1}. - Subtracts the resolved issues from the original tally and prints the remaining issues that still need attention.
There are no comments for now.