How to Zip Two Lists of Lists in Python
The built-in zip() function pairs elements from multiple iterables, but when working with lists of lists (nested lists), you often need more control over how sublists are combined. Depending on your use case, you might want to pair sublists as tuples, concatenate them into longer lists, or handle unequal lengths gracefully.
In this guide, you will learn multiple methods to zip two lists of lists in Python, from simple zip() usage to handling unequal lengths and merging sublists.
Understanding the Different "Zip" Operations
There are several ways to combine two lists of lists, and it's important to understand what each produces:
list1 = [[1, 2], [3, 4], [5, 6]]
list2 = [[7, 8], [9, 10], [11, 12]]
| Operation | Result | Description |
|---|---|---|
| Pair as tuples | [([1,2], [7,8]), ...] | Each pair is a tuple of two sublists |
| Concatenate | [[1,2,7,8], ...] | Sublists merged into longer lists |
| Element-wise merge | [[1,7,2,8], ...] | Elements interleaved |
Method 1: Pairing Sublists with zip() (Recommended)
The simplest approach uses zip() to pair corresponding sublists from both lists:
list1 = [[1, 2], [3, 4], [5, 6]]
list2 = [[7, 8], [9, 10], [11, 12]]
result = list(zip(list1, list2))
print(result)
Output:
[([1, 2], [7, 8]), ([3, 4], [9, 10]), ([5, 6], [11, 12])]
Each result element is a tuple containing the corresponding sublists from both input lists.
Using List Comprehension for Clarity
list1 = [[1, 2], [3, 4], [5, 6]]
list2 = [[7, 8], [9, 10], [11, 12]]
result = [(a, b) for a, b in zip(list1, list2)]
print(result)
Output:
[([1, 2], [7, 8]), ([3, 4], [9, 10]), ([5, 6], [11, 12])]
list(zip(list1, list2)) and the list comprehension version produce identical results. The comprehension form is useful when you need to transform the pairs during zipping (for example, when concatenating sublists).
Method 2: Concatenating Sublists
To merge corresponding sublists into single longer lists, use the + operator inside a comprehension:
list1 = [[1, 2], [3, 4], [5, 6]]
list2 = [[7, 8], [9, 10], [11, 12]]
result = [a + b for a, b in zip(list1, list2)]
print(result)
Output:
[[1, 2, 7, 8], [3, 4, 9, 10], [5, 6, 11, 12]]
This is often the desired behavior: combining related data from two sources into unified lists.
Concatenating More Than Two Lists
list1 = [[1, 2], [3, 4]]
list2 = [[5, 6], [7, 8]]
list3 = [[9, 10], [11, 12]]
result = [a + b + c for a, b, c in zip(list1, list2, list3)]
print(result)
Output:
[[1, 2, 5, 6, 9, 10], [3, 4, 7, 8, 11, 12]]
Method 3: Handling Unequal Lengths with zip_longest()
Standard zip() stops at the shortest list, silently dropping elements from longer lists:
list1 = [[1, 2], [3, 4]]
list2 = [[5, 6], [7, 8], [9, 10]]
# zip() truncates to the shorter list
result = list(zip(list1, list2))
print(result)
# [([1, 2], [5, 6]), ([3, 4], [7, 8])]
# [9, 10] is silently dropped!
Output:
[([1, 2], [5, 6]), ([3, 4], [7, 8])]
Use itertools.zip_longest() to include all elements, filling missing values with a default:
from itertools import zip_longest
list1 = [[1, 2], [3, 4]]
list2 = [[5, 6], [7, 8], [9, 10]]
result = list(zip_longest(list1, list2, fillvalue=[]))
print(result)
Output:
[([1, 2], [5, 6]), ([3, 4], [7, 8]), ([], [9, 10])]
Concatenating with zip_longest()
from itertools import zip_longest
list1 = [[1, 2], [3, 4]]
list2 = [[5, 6], [7, 8], [9, 10]]
result = [a + b for a, b in zip_longest(list1, list2, fillvalue=[])]
print(result)
Output:
[[1, 2, 5, 6], [3, 4, 7, 8], [9, 10]]
The fillvalue parameter determines what replaces missing elements. Using fillvalue=[] works well for list concatenation, while fillvalue=None is better for tuple pairing when you want to detect missing data.
Method 4: Element-Wise Interleaving
To interleave elements from corresponding sublists (alternating between them):
list1 = [[1, 2], [3, 4]]
list2 = [[5, 6], [7, 8]]
result = []
for a, b in zip(list1, list2):
interleaved = [val for pair in zip(a, b) for val in pair]
result.append(interleaved)
print(result)
Output:
[[1, 5, 2, 6], [3, 7, 4, 8]]
Compare with concatenation:
Concatenated: [[1, 2, 5, 6], [3, 4, 7, 8]]
Interleaved: [[1, 5, 2, 6], [3, 7, 4, 8]]
Method 5: Using a Loop
An explicit loop provides maximum clarity and is easy to extend with custom logic:
list1 = [[1, 3], [4, 5], [5, 6]]
list2 = [[7, 9], [3, 2], [3, 10]]
result = []
for i in range(len(list1)):
result.append(list1[i] + list2[i])
print(result)
Output:
[[1, 3, 7, 9], [4, 5, 3, 2], [5, 6, 3, 10]]
Method 6: Using NumPy for Large Numeric Data
For large numeric datasets, NumPy provides optimized array operations:
import numpy as np
list1 = [[1, 2], [3, 4], [5, 6]]
list2 = [[7, 8], [9, 10], [11, 12]]
arr1 = np.array(list1)
arr2 = np.array(list2)
# Stack arrays along a new axis (pairs sublists)
paired = np.stack([arr1, arr2], axis=1)
print("Paired:\n", paired)
# Concatenate arrays along columns
concatenated = np.concatenate([arr1, arr2], axis=1)
print("\nConcatenated:\n", concatenated)
# Element-wise addition
summed = arr1 + arr2
print("\nElement-wise sum:\n", summed)
Output:
Paired:
[[[ 1 2]
[ 7 8]]
[[ 3 4]
[ 9 10]]
[[ 5 6]
[11 12]]]
Concatenated:
[[ 1 2 7 8]
[ 3 4 9 10]
[ 5 6 11 12]]
Element-wise sum:
[[ 8 10]
[12 14]
[16 18]]
NumPy is significantly faster than pure Python for large numeric datasets. If your sublists contain numbers and performance matters, convert to NumPy arrays first.
Common Mistake: Unexpected Truncation with zip()
A frequent bug is not realizing that zip() silently truncates to the shortest input:
Problem
list1 = [[1, 2], [3, 4], [5, 6]]
list2 = [[7, 8], [9, 10]]
result = [a + b for a, b in zip(list1, list2)]
print(result)
# [[1, 2, 7, 8], [3, 4, 9, 10]]
# [5, 6] is silently dropped!
Output:
[[1, 2, 7, 8], [3, 4, 9, 10]]
Fix: use zip_longest() or validate lengths
from itertools import zip_longest
list1 = [[1, 2], [3, 4], [5, 6]]
list2 = [[7, 8], [9, 10]]
# Option 1: Use zip_longest
result = [a + b for a, b in zip_longest(list1, list2, fillvalue=[])]
print(result) # [[1, 2, 7, 8], [3, 4, 9, 10], [5, 6]]
# Option 2: Validate lengths first
if len(list1) != len(list2):
print(f"Warning: lists have different lengths ({len(list1)} vs {len(list2)})")
Output:
[[1, 2, 7, 8], [3, 4, 9, 10], [5, 6]]
Warning: lists have different lengths (3 vs 2)
Comparison of Methods
| Method | Operation | Handles Unequal Lengths | Best For |
|---|---|---|---|
zip() + tuples | Pair sublists | ❌ Truncates | Simple pairing |
zip() + concatenation | Merge sublists | ❌ Truncates | Combining related data |
zip_longest() | Pair/merge with fill | ✅ Yes | Unequal-length lists |
| Loop | Custom merging | ⚠️ Manual check | Complex logic, debugging |
| NumPy | Array operations | ❌ Requires same shape | Large numeric datasets |
Summary
Zipping two lists of lists in Python can mean different things depending on your needs. Key takeaways:
- Use
zip()to pair corresponding sublists: the simplest and most common approach. - Use
a + bin a comprehension to concatenate sublists into longer lists. - Use
zip_longest()when lists have different lengths to avoid silent data loss. - Use NumPy for large numeric datasets where performance matters.
- Be aware that
zip()truncates to the shortest input: always verify list lengths or usezip_longest()when lengths might differ.