Skip to main content

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]]
OperationResultDescription
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

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])]
tip

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]]
info

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]]
tip

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

MethodOperationHandles Unequal LengthsBest For
zip() + tuplesPair sublists❌ TruncatesSimple pairing
zip() + concatenationMerge sublists❌ TruncatesCombining related data
zip_longest()Pair/merge with fill✅ YesUnequal-length lists
LoopCustom merging⚠️ Manual checkComplex logic, debugging
NumPyArray operations❌ Requires same shapeLarge 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 + b in 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 use zip_longest() when lengths might differ.