Using the zipped-transpose idiom, zip upto the longest list with itertools.zip_longest
. Then iterate over each item in the sub-lists, filtering out None
values.
from itertools import zip_longest
for i in zip_longest(*data.values()):
for j in filter(None, i):
print(j)
cup
one
five
pen
two
Here, data
is your input dictionary. Don't use dict
to name variables, it shadows the builtin class with the same name.
Note that this order is not guaranteed on python versions below python-3.6, since dictionaries are not ordered in these older versions of python.
Final note, for python-2.x, the appropriate function to be used is itertools.izip_longest
.
The output of zip_longest
looks like this:
print(list(zip_longest(*data.values())))
[('cup', 'one', 'five'), ('pen', 'two', None)]
These None
values are inserted in place of missing values due to the "zip longest' behaviour of the function. These None
s are removed with filter
.
You can use this to get creative using itertools.chain
and a print
statement, accomplishing this in one line:
from itertools import chain
print(*filter(None, chain.from_iterable(zip_longest(*data.values()))), sep='\n')
cup
one
five
pen
two
Re-written a little more clearly:
print(
*filter( # `filter` out None (iterable unpacking)
None,
chain.from_iterable( # flatten an iterable of iterables
zip_longest(*data.values()) # zip-longest transpose
)
),
sep='\n' # separate unpacked arguments with newline
)
One more option, for homework submission without zip_longest
. This just cycles over the keys, popping one element at a time from each list.
while any(bool(v) for v in data.values()):
for k in data:
try:
print(data[k].pop(0))
except IndexError:
pass
cup
one
five
pen
two
This empties data
of its contents, so you may want to make a copy of your data beforehand.