Is there a zip-like function that pads to longest length?
In Python 3 you can use itertools.zip_longest
>>> list(itertools.zip_longest(a, b, c))
[('a1', 'b1', 'c1'), (None, 'b2', 'c2'), (None, 'b3', None)]
You can pad with a different value than None
by using the fillvalue
parameter:
>>> list(itertools.zip_longest(a, b, c, fillvalue='foo'))
[('a1', 'b1', 'c1'), ('foo', 'b2', 'c2'), ('foo', 'b3', 'foo')]
With Python 2 you can either use itertools.izip_longest
(Python 2.6+), or you can use map
with None
. It is a little known feature of map
(but map
changed in Python 3.x, so this only works in Python 2.x).
>>> map(None, a, b, c)
[('a1', 'b1', 'c1'), (None, 'b2', 'c2'), (None, 'b3', None)]
zip()-like built-in function filling unequal lengths from left with None value
Use zip_longest
but reverse lists.
Example:
from itertools import zip_longest
header = ["title", "firstname", "lastname"]
person_1 = ["Dr.", "Joe", "Doe"]
person_2 = ["Mary", "Poppins"]
person_3 = ["Smith"]
print(dict(zip_longest(reversed(header), reversed(person_2))))
# {'lastname': 'Poppins', 'firstname': 'Mary', 'title': None}
On your use cases:
>>> dict(zip_longest(reversed(header), reversed(person_1)))
{'title': 'Dr.', 'lastname': 'Doe', 'firstname': 'Joe'}
>>> dict(zip_longest(reversed(header), reversed(person_2)))
{'lastname': 'Poppins', 'firstname': 'Mary', 'title': None}
>>> dict(zip_longest(reversed(header), reversed(person_3)))
{'lastname': 'Smith', 'firstname': None, 'title': None}
Python, How to zip unequal sized list, if one list 's length less than another, than fill None
i think you want itertools.zip_longest
>>> list1=[1,2,3]
>>> list2=[1,2,3,4]
>>> import itertools
>>> list(itertools.zip_longest(list1, list2))
[(1, 1), (2, 2), (3, 3), (None, 4)]
How to zip lists of different sizes?
It's not pretty, but this is what I came up with:
In [10]: a = [1, 3, 5, 7, 9, 11]
...: b = [2, 4, 6, 8]
In [11]: output = (tuple(l[i] for l in (a,b) if i < len(l)) for i, e in enumerate(max(a,b, key=len)))
In [12]: list(output)
Out[12]: [(1, 2), (3, 4), (5, 6), (7, 8), (9,), (11,)]
Make it a function:
from collections.abc import (Iterable, Iterator)
from itertools import count
def zip_staggered(*args: Iterable) -> Iterator[tuple]:
for i in count():
if (next_elem := tuple(a[i] for a in args if i < len(a))):
yield next_elem
else:
break
adding list of different lengths together
Below code will help you to print a new list as expected
from itertools import cycle
firstlist = ['A','B','C','D','E']
secondlist = ['1','2','3','4','5','6','7','8','9','10']
res = [[x, y] for x, y in zip(cycle(firstlist), secondlist)]
print(res)
Use last element of list untile loop is complete
My suggestion:
res=[str(i)+k for (i, k) in zip(b, a+[a[-1]]*(len(b)-len(a)))]
>>>print(res)
['1st', '2nd', '3rd', '4th', '5th', '6th', '7th', '8th']
Creating a function that works like zip
Try this one.
def zip_copy(*args):
lst = []
i = 0
t = tuple()
for a in range(len(min(args,key=len))):
for a in args:
t+=(a[i],)
i+=1
lst +=(t,)
t = tuple()
return lst
print(zip_copy([1,2],[3,4],[3,5])) # [(1, 3, 3), (2, 4, 5)]
print(list(zip([1,2],[3,4],[3,5]))) # [(1, 3, 3), (2, 4, 5)]
# ------------------------------------#
print(zip_copy([1,2])) # [(1,), (2,)]
print(list(zip([1,2]))) # [(1,), (2,)]
# ------------------------------------ #
print(zip_copy("Hello","Hii")) # [('H', 'H'), ('e', 'i'), ('l', 'i')]
print(list(zip("Hello","Hii"))) # [('H', 'H'), ('e', 'i'), ('l', 'i')]
Is there more to enumerate() than just zip(range(len()))?
Because not every iterable has a length.
>>> def countdown(x):
... while x >= 0:
... yield x
... x -= 1
...
>>> down = countdown(3)
>>> len(down)
Traceback (most recent call last):
[...]
TypeError: object of type 'generator' has no len()
>>> enum = enumerate(down)
>>> next(enum)
(0, 3)
>>> next(enum)
(1, 2)
This is a trivial example, of course. But I could think of lots of real world objects where you can't reasonably pre-compute a length. Either because the length is infinite (see itertools.count
) or because the object you are iterating over does itself not know when the party is over.
Your iterator could be fetching chunks of data from a remote database of unknown size or to which the connection might get lost without warning. Or it could process user input.
def get_user_input():
while True:
i = input('input value or Q to quit: ')
if i == 'Q':
break
yield i
You cannot get the length of get_user_input()
, but you can enumerate
all inputs as you fetch them via next
(or iteration).
Related Topics
How to Select a Variable by (String) Name
Use a List of Values to Select Rows from a Pandas Dataframe
How to Find Overlapping Matches With a Regexp
Difference Between Del, Remove, and Pop on Lists
Why Is Python Running My Module When I Import It, and How to Stop It
Delete a Column from a Pandas Dataframe
Permanently Add a Directory to Pythonpath
Word Boundary With Words Starting or Ending With Special Characters Gives Unexpected Results
Equivalent of Shell 'Cd' Command to Change the Working Directory
How to Check Which Version of Python Is Running My Script
Create a Pandas Dataframe by Appending One Row At a Time
How to Use Raw_Input in Python 3
Process Escape Sequences in a String in Python