Python
Nested Lists
List Intersection
Data Structures
Programming Tips

Find intersection of two nested lists?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

The phrase "intersection of two nested lists" is ambiguous, and that ambiguity matters more than the code. Sometimes you want the inner lists treated as whole items, and other times you want to flatten the structure and intersect the scalar values inside. The right implementation depends on which meaning you actually need.

Treat Inner Lists as the Elements

Suppose the inner lists themselves are the things you want to compare:

python
a = [[1, 2], [3, 4], [5, 6]]
b = [[3, 4], [7, 8], [1, 2]]

In that case, the expected answer is the shared sublists. The main obstacle is that lists are unhashable, so they cannot go directly into a set. The usual fix is to convert each inner list to a tuple for comparison:

python
1a = [[1, 2], [3, 4], [5, 6]]
2b = [[3, 4], [7, 8], [1, 2]]
3
4common = set(map(tuple, a)) & set(map(tuple, b))
5result = [list(item) for item in common]
6
7print(result)

This is a clean solution when each sublist is a record-like value and order inside the sublist matters as part of equality.

Preserve Source Order When Needed

Set intersection is efficient, but it does not preserve order. If the result should keep the order of the first input, build a lookup set from one side and scan the other side in sequence:

python
1a = [[1, 2], [3, 4], [5, 6]]
2b = [[3, 4], [7, 8], [1, 2]]
3
4b_lookup = set(map(tuple, b))
5result = [item for item in a if tuple(item) in b_lookup]
6
7print(result)

This keeps the ordering from a while still using fast membership checks.

If duplicates matter, then plain sets are no longer enough. You may need a counting approach such as Counter on tuple-converted rows.

Flatten First If You Mean Shared Scalar Values

Sometimes the nesting is incidental and you really want the numbers or strings that appear anywhere in both structures. In that case, flatten first and then intersect:

python
1a = [[1, 2], [3, 4]]
2b = [[2, 4], [6, 8]]
3
4flat_a = [value for row in a for value in row]
5flat_b = [value for row in b for value in row]
6
7common = set(flat_a) & set(flat_b)
8print(common)

This answers a completely different question from the earlier example. Instead of comparing rows as units, it finds shared scalar values regardless of where they appeared.

That is why clarifying the requirement is the most important step. Many nested-list intersection bugs come from solving the wrong interpretation correctly.

Handle Deeper Nesting with Recursive Flattening

If the nesting depth is not fixed, you can flatten recursively:

python
1def flatten(values):
2    for item in values:
3        if isinstance(item, list):
4            yield from flatten(item)
5        else:
6            yield item
7
8
9a = [[1, [2, 3]], [4]]
10b = [[3, 4], [5, [1]]]
11
12common = set(flatten(a)) & set(flatten(b))
13print(common)

This is useful for irregular data, but it also changes the meaning of the structure. Once you flatten recursively, the grouping information carried by the nested lists is gone.

Count Duplicates Only If the Problem Requires It

If you want intersection with multiplicity, use a counting structure rather than a plain set. For nested rows treated as elements, convert rows to tuples and then count them:

python
1from collections import Counter
2
3rows_a = list(map(tuple, [[1, 2], [1, 2], [3, 4]]))
4rows_b = list(map(tuple, [[1, 2], [5, 6]]))
5
6common = Counter(rows_a) & Counter(rows_b)
7result = [list(item) for item in common.elements()]
8
9print(result)

Now repeated rows are preserved according to the minimum count in both inputs.

Common Pitfalls

The biggest mistake is calling set(a) when a contains inner lists. Python will raise TypeError because lists are unhashable.

Another issue is not deciding whether the nested lists are items or structure. Intersecting rows as whole units and intersecting flattened values are different tasks with different answers.

People also get surprised when sets remove duplicates and reorder the result. That is standard set behavior, not a bug.

Finally, recursive flattening should be used carefully. It is powerful, but it silently throws away grouping information that may actually matter to the application.

Summary

  • If inner lists are the elements, convert them to tuples and intersect those.
  • If you want shared scalar values anywhere inside the structure, flatten first and then intersect.
  • Use an ordered scan when source order matters.
  • Use counting instead of plain sets when duplicates matter.
  • The key decision is the meaning of "intersection" for your nested data, not just the syntax.

Course illustration
Course illustration

All Rights Reserved.