Explain Codes LogoExplain Codes Logo

Unpacking a list / tuple of pairs into two lists / tuples

python
list-comprehensions
generator-expressions
zip-function
Anton ShumikhinbyAnton Shumikhin·Mar 9, 2025
TLDR

Unpack pairs into two lists with one line: use the zip function coupled with unpacking (*). Here's the secret sauce:

pairs = [(1, 'a'), (2, 'b'), (3, 'c')] # Unpacking into tuples a, b = zip(*pairs) # Transformers, tuples in disguise! # Need lists instead? a, b = map(list, zip(*pairs)) # Listify the tuples!

Now, you've got a as (1, 2, 3) or [1, 2, 3], and b as ('a', 'b', 'c') or ['a', 'b', 'c'].

Other ways to skin the cat

Though the zip with unpacking is super efficient and pythonic, there are more rabbits (methods) in the hat.

List comprehensions: when thinking inside the box works

List comprehensions can be a friendlier approach:

numbers = [num for num, _ in pairs] # Pick the numbers letters = [letter for _, letter in pairs] # And the letters

Generators: your memory’s best friends

To optimize memory management, especially with large datasets, you can flex with generator expressions:

numbers_gen = (num for num, _ in pairs) # Generator power! letters_gen = (letter for _, letter in pairs) # Keep it lean!

As always, you can later mold these generators into lists or tuples if you fancy so.

The edge cases: no unpacking is left behind

We’ve covered common grounds, but let's see how versatile this unpacking thing is when the going gets weird.

Nested nightmares: unpacking inception

With multi-layered nested structures, zip can still rock it:

nested_pairs = [((1, 'a'), 'x'), ((2, 'b'), 'y'), ((3, 'c'), 'z')] (a, b), c = zip(*nested_pairs) # Unpacking like we're in the Matrix

Unequal lengths: because life’s not fair

If the pair lengths differ, itertools.zip_longest comes to the rescue:

from itertools import zip_longest pairs = [(1, 'a'), (2, 'b', 'extra'), (3, 'c')] a, b = zip_longest(*pairs, fillvalue=None) # Filling in for Sancho Panza

Repacking the suitcase: the reverse gear of zip

Need to combine lists back into pairs? Just zip in reverse:

combined = list(zip(numbers, letters)) # Pairs are friends again!

This action is essentially the retrograde of our initial unpacking, showcasing the utility of zip.

The unpacking cautionary tale

Zip is great, but use caution when:

  1. Pair elements are not uniform, which can lead to silent data slaughter.
  2. Memory is of the essence with humongous datasets.

In these cases, you may want to check out alternative methods like the good old explicit loops or list comprehensions.