Combining Iterables with Fillvalue

  • Share this:

Code introduction


This function combines multiple iterable objects (like lists or tuples) into one iterable that aggregates elements from each of the provided iterables.


Technology Stack : collections, itertools, bisect

Code Type : Function

Code Difficulty : Intermediate


                
                    
def zip_longest(*args, fillvalue=None):
    """Combine multiple iterables (like lists or tuples) into one iterable that aggregates elements from each of the iterables.

    Args:
        *args: An arbitrary number of iterables to be zipped.
        fillvalue: The value to use for missing values in shorter iterables.

    Yields:
        A tuple containing one element from each of the provided iterables.

    """
    from itertools import zip_longest
    from collections import deque
    from bisect import insort_left

    # Create a deque of all iterables to iterate over
    iterables = [deque(iterable) for iterable in args]
    # Create a list to hold the current elements from each iterable
    current_elements = []

    while True:
        # Find the longest iterable and its last element
        max_length = 0
        last_element = None
        for i, iterable in enumerate(iterables):
            if iterable:
                max_length = len(iterable)
                last_element = iterable[-1]
            else:
                insort_left(current_elements, (i, fillvalue))
        if max_length == 0:
            break

        # Yield the current elements
        yield tuple(current_elements)

        # Update the iterables and the current elements list
        for i, iterable in enumerate(iterables):
            if iterable:
                iterable.popleft()
            else:
                if current_elements:
                    current_elements.pop(0)
                else:
                    break