Python
itertools
groupby
Python programming
data processing

How do I use itertools.groupby?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

itertools.groupby is useful when you want to group consecutive items that share the same key. The most important thing to remember is that it does not do SQL-style global grouping on arbitrary input. It groups runs of adjacent values, which makes ordering central to correct use.

Understand What groupby Returns

groupby(iterable, key=...) yields pairs of:

  • the group key
  • an iterator over the items in that consecutive group

Example:

python
1from itertools import groupby
2
3rows = [
4    ("books", "Clean Code"),
5    ("games", "Go"),
6    ("books", "Refactoring"),
7]
8
9for category, group in groupby(rows, key=lambda row: row[0]):
10    print(category, [title for _, title in group])

This produces two separate books groups because the books rows are not adjacent in the original input.

Sort First When You Need Global Grouping

If you want one group per key across the whole dataset, sort by the same key first:

python
1from itertools import groupby
2
3rows = [
4    ("books", "Clean Code"),
5    ("games", "Go"),
6    ("books", "Refactoring"),
7    ("games", "Chess"),
8]
9
10rows_sorted = sorted(rows, key=lambda row: row[0])
11
12for category, group in groupby(rows_sorted, key=lambda row: row[0]):
13    print(category, [title for _, title in group])

The sort key and the grouping key should match. Sorting by one field and grouping by another is a common cause of confusing output.

Consume Group Iterators Immediately

Each group iterator shares the underlying input stream. Once the outer loop advances, the previous group is effectively gone.

If you need to reuse the grouped items, materialize them immediately:

python
1from itertools import groupby
2
3data = [1, 1, 2, 2, 2, 3]
4result = []
5
6for key, grp in groupby(data):
7    items = list(grp)
8    result.append((key, items, len(items)))
9
10print(result)

That is the right pattern when you need both the items and a derived statistic such as the count.

Aggregate While Grouping

groupby is great for sorted record streams where you want streaming-style aggregation:

python
1from itertools import groupby
2
3records = [
4    {"team": "A", "score": 8},
5    {"team": "B", "score": 7},
6    {"team": "A", "score": 12},
7    {"team": "B", "score": 10},
8]
9
10records.sort(key=lambda row: row["team"])
11
12summary = []
13for team, grp in groupby(records, key=lambda row: row["team"]):
14    rows = list(grp)
15    total = sum(row["score"] for row in rows)
16    summary.append((team, total, len(rows)))
17
18print(summary)

If the groups are large, you can aggregate directly from the iterator instead of materializing the whole group into a list.

Know When a Dictionary Is Better

groupby shines when the input is already sorted or naturally ordered. If the data arrives in arbitrary order and you need global grouping without sorting, a dictionary-based accumulation approach may be simpler.

That does not make groupby wrong. It just means its strength is ordered grouping, not universal aggregation across random input.

Nested Grouping Works in Stages

You can group by multiple levels by sorting on a composite key and then grouping in stages:

python
1from itertools import groupby
2
3events = [
4    ("2026-03", "A", 3),
5    ("2026-03", "A", 5),
6    ("2026-03", "B", 2),
7    ("2026-04", "A", 4),
8]
9
10events.sort(key=lambda row: (row[0], row[1]))
11
12for month, month_group in groupby(events, key=lambda row: row[0]):
13    print("month", month)
14    for team, team_group in groupby(month_group, key=lambda row: row[1]):
15        total = sum(value for _, _, value in team_group)
16        print(" ", team, total)

This keeps the processing stream-oriented and avoids unnecessary intermediate structures.

Common Pitfalls

The biggest mistake is expecting groupby to combine matching keys across unsorted input.

Another issue is sorting by one key and grouping by another, which fragments the data in surprising ways.

People also try to reuse group iterators after the outer loop moves on, which does not work because the iterators are single-pass.

Summary

  • 'itertools.groupby groups consecutive items, not arbitrary matching keys across unsorted input.'
  • Sort first when you need one global group per key.
  • Consume or materialize each group immediately because the iterators are single-pass.
  • Use groupby for ordered data and dictionary accumulation for unordered aggregation.
  • Keep the sort key and the group key aligned.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.