Skip to content

How to Group a List of Tuples into a Dictionary by Key in Python

Learn efficient Python techniques to transform a list of key-value tuples into a dictionary where each key maps to a list of associated values using defaultdict, setdefault, or itertools.groupby.

Converting a list of key-value tuples into a dictionary where each key maps to a list of associated values is a common data transformation task.

The defaultdict from the collections module provides the cleanest and most efficient solution:

from collections import defaultdict

data = [(1, 'A'), (1, 'B'), (2, 'C'), (2, 'D'), (3, 'E')]

grouped = defaultdict(list)
for key, value in data:
    grouped[key].append(value)

print(dict(grouped))

Using setdefault (No Imports)

When avoiding imports, setdefault provides similar functionality:

data = [(1, 'A'), (1, 'B'), (2, 'C'), (2, 'D'), (3, 'E')]

grouped = {}
for key, value in data:
    grouped.setdefault(key, []).append(value)

print(grouped)

The setdefault method returns the existing value for a key or sets and returns the default if the key does not exist.

Grouping with Sets (Unique Values)

To collect only unique values per key, use sets instead of lists:

from collections import defaultdict

data = [(1, 'A'), (1, 'A'), (1, 'B'), (2, 'C')]

grouped = defaultdict(set)
for key, value in data:
    grouped[key].add(value)

print(dict(grouped))

Grouping Objects by Attribute

Apply the same pattern to group objects:

from collections import defaultdict

class Product:
    def __init__(self, name, category):
        self.name = name
        self.category = category

products = [
    Product("Apple", "Fruit"),
    Product("Banana", "Fruit"),
    Product("Carrot", "Vegetable"),
]

by_category = defaultdict(list)
for product in products:
    by_category[product.category].append(product.name)

print(dict(by_category))

Using itertools.groupby

For pre-sorted data, groupby offers a functional approach:

from itertools import groupby

data = [(1, 'A'), (1, 'B'), (2, 'C'), (2, 'D')]

data_sorted = sorted(data, key=lambda x: x[0])

grouped = {
    key: [v for _, v in group]
    for key, group in groupby(data_sorted, key=lambda x: x[0])
}

print(grouped)

Avoid the O(N²) Trap

A nested comprehension approach looks elegant but performs terribly:

data = [(1, 'A'), (1, 'B'), (2, 'C')]

grouped = {
    k: [v for k2, v in data if k2 == k]
    for k, _ in data
}
print(grouped)

This iterates through the entire list for every tuple, making it quadratic complexity.

from collections import defaultdict

data = [(1, 'A'), (1, 'B'), (2, 'C')]

grouped = defaultdict(list)
for k, v in data:
    grouped[k].append(v)

print(dict(grouped))

Grouping Multiple Values

When tuples have more than two elements:

from collections import defaultdict

data = [
    ('Fruit', 'Apple', 1.50),
    ('Fruit', 'Banana', 0.75),
    ('Vegetable', 'Carrot', 0.50),
]

grouped = defaultdict(list)
for category, product, price in data:
    grouped[category].append({'product': product, 'price': price})

print(dict(grouped))

Aggregating Instead of Collecting

Sometimes you want to aggregate values rather than collect them:

from collections import defaultdict

sales = [('Jan', 100), ('Jan', 150), ('Feb', 200), ('Feb', 50)]

totals = defaultdict(int)
for month, amount in sales:
    totals[month] += amount

print(dict(totals))

Method Comparison

Method Time Complexity Imports Best For
defaultdict(list) O(N) Yes General use
setdefault O(N) No Import-free code
groupby O(N log N)* Yes Pre-sorted data
Nested comprehension O(N²) No Never use

*Includes sorting time

Summary

  • Use defaultdict(list) as your default approach for grouping; it is efficient, readable, and handles missing keys automatically.
  • Use setdefault when you want to avoid imports.
  • Avoid nested comprehensions for grouping as they create O(N²) performance problems.
Navigation