Combining Iterables with FillValue

  • Share this:

Code introduction


This function utilizes libraries such as itertools, collections, operator, math, functools, heapq, and bisect to combine multiple iterable objects into a new iterator, where shorter sequences are filled with a specified fill value.


Technology Stack : itertools, collections, operator, math, functools, heapq, bisect

Code Type : Function

Code Difficulty : Intermediate


                
                    
def zip_longest(*args, fillvalue=0):
    from itertools import zip_longest
    from collections import deque
    from operator import itemgetter
    from math import inf
    from functools import reduce
    from heapq import heappush, heappop
    from bisect import insort

    def get_longest(*iterables):
        max_length = max(map(len, iterables))
        for i in range(max_length):
            if any((len(it) <= i for it in iterables)):
                return max_length
        return max_length

    longest = get_longest(*args)
    iters = [deque(iterable) for iterable in args]
    indices = [0] * len(args)
    while True:
        next_values = [iterable[indices[i]] for i, iterable in enumerate(iters)]
        if any((v is None for v in next_values)):
            break
        yield tuple(next_values)
        for i, value in enumerate(next_values):
            iters[i].popleft()
            if iters[i]:
                indices[i] = 0
            else:
                indices[i] = inf

    while args:
        for i, iterable in enumerate(args):
            if iterable:
                yield (iterable[0],) * len(args)
                iterable.popleft()
                args[i] = iterable

    for _ in range(longest - get_longest(*args)):
        yield tuple(fillvalue) * len(args)