Is There a Zip-Like Function That Pads to Longest Length

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



Leave a reply



Submit