Zipping lists of unequal size

Normally, you use itertools.zip_longest for this:

>>> import itertools
>>> a = [1, 2, 3]
>>> b = [9, 10]
>>> for i in itertools.zip_longest(a, b): print(i)
... 
(1, 9)
(2, 10)
(3, None)

But zip_longest pads the shorter iterable with Nones (or whatever value you pass as the fillvalue= parameter). If that’s not what you want then you can use a comprehension to filter out the Nones:

>>> for i in (tuple(p for p in pair if p is not None) 
...           for pair in itertools.zip_longest(a, b)):
...     print(i)
... 
(1, 9)
(2, 10)
(3,)

but note that if either of the iterables has None values, this will filter them out too. If you don’t want that, define your own object for fillvalue= and filter that instead of None:

sentinel = object()

def zip_longest_no_fill(a, b):
    for i in itertools.zip_longest(a, b, fillvalue=sentinel):
        yield tuple(x for x in i if x is not sentinel)

list(zip_longest_no_fill(a, b))  # [(1, 9), (2, 10), (3,)]

Leave a Comment