If I have two iterables of different lengths, how can I most cleanly pair them, re-using values from the shorter one until all values from the longer are consumed?
For example, given two lists
l1 = ['a', 'b', 'c']
l2 = ['x', 'y']
It would be desirable to have a function fn()
resulting in pairs:
>>> fn(l1, l2)
[('a', 'x'), ('b', 'y'), ('c', 'x')]
I found I could write a function to perform this as such
def fn(l1, l2):
if len(l1) > len(l2):
return [(v, l2[i % len(l2)]) for i, v in enumerate(l1)]
return [(l1[i % len(l1)], v) for i, v in enumerate(l2)]
>>> fn(l1, l2)
[('a', 'x'), ('b', 'y'), ('c', 'x')]
>>> l2 = ['x', 'y', 'z', 'w']
>>> fn(l1,l2)
[('a', 'x'), ('b', 'y'), ('c', 'z'), ('a', 'w')]
However, I'm greedy and was curious what other methods exist? so that I may select the most obvious and elegant and be wary of others.
itertools.zip_longest
as suggested in many similar questions is very close to my desired use case as it has a fillvalue
argument which will pad the longer pairs. However, this only takes a single value, instead of wrapping back to the first value in the shorter list.
As a note: in my use case one list will always be much shorter than the other and this may allow a short-cut, but a generic solution would be exciting too!