How to Group Data in Python with defaultdict and Comprehensions

Group a list of items by a computed key using a defaultdict-based generator helper and an alternative dictionary comprehension approach.

Easy Python 3.9+ Aug 9, 2026 Comprehensions & generators 15 views 0 copies

Python code

31 lines
Python 3.9+
from collections import defaultdict

def group_by(data, key_func):
    """Group items in data by the value returned by key_func."""
    result = defaultdict(list)
    for item in data:
        result[key_func(item)].append(item)
    return dict(result)

def group_by_comprehension(data, key_func):
    """Same grouping using a dictionary comprehension with a set of unique keys."""
    return {key: [item for item in data if key_func(item) == key]
            for key in {key_func(item) for item in data}}

if __name__ == "__main__":
    people = [
        {"name": "Alice", "age": 30},
        {"name": "Bob", "age": 25},
        {"name": "Charlie", "age": 30},
        {"name": "Diana", "age": 25},
    ]

    by_age = group_by(people, lambda p: p["age"])
    print("Using generator-based helper:")
    for age, group in sorted(by_age.items()):
        print(f"  Age {age}: {[p['name'] for p in group]}")

    by_age_comp = group_by_comprehension(people, lambda p: p["age"])
    print("Using comprehension-based helper:")
    for age, group in sorted(by_age_comp.items()):
        print(f"  Age {age}: {[p['name'] for p in group]}")

Output

stdout
Using generator-based helper:
  Age 25: ['Bob', 'Diana']
  Age 30: ['Alice', 'Charlie']
Using comprehension-based helper:
  Age 25: ['Bob', 'Diana']
  Age 30: ['Alice', 'Charlie']

How it works

The group_by function uses defaultdict(list) to avoid checking if a key already exists; appending to a missing key automatically creates an empty list. The comprehension-based variant first builds a set of unique keys with a set comprehension, then uses a dictionary comprehension that scans the data once per key — simpler to read but O(n²) for large datasets. Both produce identical grouping, demonstrating two idioms for the same task: the procedural loop is efficient and clear, while the comprehension is compact and functional. For production code with large inputs, prefer the defaultdict approach for linear time.

Common mistakes

  • Forgetting to convert defaultdict back to a normal dict with dict() when you need a plain dictionary.
  • Using a list comprehension repeatedly inside a dict comprehension causes O(n²) time on large data.
  • Assuming the key function returns hashable values; if not, grouping will fail.
  • Not sorting keys before printing, which makes output order unpredictable.

Variations

  1. Use itertools.groupby after sorting data by the key for memory-efficient grouping of consecutive runs.
  2. Use pandas groupby() to group DataFrame rows by a column when working with tabular data.

Real-world use cases

  • Grouping API response records by user ID before rendering a dashboard.
  • Batching log entries by error code to aggregate error counts per service.
  • Partitioning inventory items by category to generate per-category reports.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Comprehensions & generators

Related tutorials and quizzes for this topic.