Skip to content

Instantly share code, notes, and snippets.

@carcigenicate
Last active December 27, 2020 15:23
Show Gist options
  • Save carcigenicate/85791d4818d1bf30c9f405ad820c451e to your computer and use it in GitHub Desktop.
Save carcigenicate/85791d4818d1bf30c9f405ad820c451e to your computer and use it in GitHub Desktop.
def my_zip(*iterables):
iters = [iter(i) for i in iterables]
while True:
try:
yield tuple([next(it) for it in iters])
except StopIteration:
return
@danielhao5
Copy link

Very nice - reverse engineering? How to modify to come up with zip_longest()?
Thanks for sharing.

@carcigenicate
Copy link
Author

carcigenicate commented Dec 24, 2020

@danielhao5

That's a little bit harder since you can't just rely on StopIteration being thrown.

This is suboptimal, but off the top of my head:

from typing import Optional, TypeVar

T = TypeVar("T")

def my_zip_longest(*iterables: T, fill_value: Optional[T] = None):
    iters = [iter(i) for i in iterables]
    sentinel = object()
    while True:
        raw = [next(it, sentinel) for it in iters]
        if all(obj is sentinel for obj in raw):
            return
        else:
            yield tuple([fill_value if obj is sentinel else obj for obj in raw])

I don't like the fact that it requires potentially two full iterations of raw per yield, but at the moment, I can't think of how you'd differentiate between a fill_value that coincides with legitimate elements of the list, and all the iterables simply being exhausted.

@danielhao5
Copy link

Thanks. That's quite advanced, and it did work!

Have a nice Holidays!

@carcigenicate
Copy link
Author

@danielhao5 No problem, and you as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment