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
177: The itertools Module: groupby
How does groupby actually work?
Think of itertools.groupby as a tool that scans through your data and says, "Okay, I'm seeing a bunch of the same things here; I'll bundle them together until I hit something different." It doesn't look ahead or search the whole list—it just looks at the current streak of identical values.
It returns an iterator that yields pairs: a key (the value being grouped) and a group (another iterator containing all the items in that streak). I usually convert that inner group to a list immediately because if you don't, you'll lose the data the moment the main loop moves to the next key.
from itertools import groupby
# A simple list of order statuses
orders = ['Pending', 'Pending', 'Shipped', 'Shipped', 'Shipped', 'Delivered']
for status, group in groupby(orders):
print(f"Status: {status}, Count: {len(list(group))}")
# Output:
# Status: Pending, Count: 2
# Status: Shipped, Count: 3
# Status: Delivered, Count: 1
Wait, why is it missing some of my groups?
This is the single most common mistake I see with groupby. If your data isn't sorted by the grouping key, groupby will create a new group every time the value changes. It's not like a SQL GROUP BY statement that scans the whole table; it's a linear scan.
If you have a list like ['A', 'B', 'A'], groupby will give you three groups: one for 'A', one for 'B', and another one for 'A'. If you want all the 'A's together, you must sort the data first. It feels redundant, but it's how the tool is designed to stay memory-efficient.
from itertools import groupby
data = ['Apple', 'Banana', 'Apple', 'Cherry', 'Banana']
# WRONG WAY:
for key, group in groupby(data):
print(key, list(group))
# This gives us 5 groups because nothing is consecutive.
# RIGHT WAY:
data.sort()
for key, group in groupby(data):
print(key, list(group))
# Now we get Apple [Apple, Apple], Banana [Banana, Banana], etc.
Can I group by something other than the item itself?
Absolutely. You can pass a key function as the second argument. This is incredibly useful when you're dealing with complex objects, like dictionaries or class instances, and you only want to group by one specific property.
For example, imagine you have a list of employees and you want to group them by their department. You'd use a lambda function or operator.itemgetter to tell groupby which field to look at. Just remember: you have to sort the list by that same key function before grouping, or you'll run into the same issue we just discussed.
from itertools import groupby
from operator import itemgetter
employees = [
{'name': 'Alice', 'dept': 'Engineering'},
{'name': 'Bob', 'dept': 'Sales'},
{'name': 'Charlie', 'dept': 'Engineering'},
{'name': 'David', 'dept': 'Sales'},
]
# Sort by 'dept' first!
employees.sort(key=itemgetter('dept'))
for dept, group in groupby(employees, key=itemgetter('dept')):
print(f"Department: {dept}")
for emp in group:
print(f" - {emp['name']}")
# Output:
# Department: Engineering
# - Alice
# - Charlie
# Department: Sales
# - Bob
# - David
📋 Practical Task
Exercise: Organizing Transaction Logs by Date
You have a list of transaction tuples in the format (date, amount, category). The list is currently unsorted. Your task is to use itertools.groupby to calculate the total spend for each unique date.
Requirements:
- Sort the data by date first.
- Use
groupbyto isolate transactions for each date. - Sum the
amountfor all transactions within that date group. - Print the result as:
Date: YYYY-MM-DD, Total: X
transactions = [
('2023-10-01', 50.00, 'Groceries'),
('2023-10-02', 20.00, 'Coffee'),
('2023-10-01', 15.50, 'Transport'),
('2023-10-03', 100.00, 'Electronics'),
('2023-10-02', 35.00, 'Lunch'),
]
# Your code here
There are no comments for now.