For a function that transposes a list using zip, there’s the case were the list of entries is empty, then zip returns an empty iterator instead of an iterator of empty containers. I understand that with no entries the zip function cannot deduce any dimensions, so it is reasonable to return nothing. What would be the best way of handling that? Is there a general way to solve this?
T = TypeVar("T") U = TypeVar("U") def transpose2(entries: Iterable[Tuple[T, U]]) -> Tuple[Iterable[T], Iterable[U]]: # Broken when len(list(entries)) == 0 first, second = zip(*entries) return first, second
T = TypeVar("T") U = TypeVar("U") def transpose2(entries: Iterable[Tuple[T, U]]) -> Tuple[Iterable[T], Iterable[U]]: # Ugly fix first_second = tuple(zip(*entries)) first, second = (list(first_second), list(first_second)) if len(first_second) > 1 else (, ) return first, second
This is toy function, here’s the function where I stumbled upon this
def scatter_annotated( entries: Iterable[Tuple[str, Tuple[Number, Number]]], ax: matplotlib.axes.Axes, scatter_kwarg: Dict[str, Any], annotate_kwarg: Dict[str, Any]): """Adds a scatter plot to the axis and annotates each point""" def annotate(entry: Tuple[str, Tuple[Number, Number]]): ax.annotate(*entry, **annotate_kwarg) # more_itertools.side_effect entries = side_effect(annotate, entries) xy = unzip(((x, y) for _, (x, y) in entries)) # In the case of no entries, xy becomes an empty tuple instead # of a tuple of two empty lists x, y = (list(xy), list(xy)) if len(xy) > 1 else (, ) ax.scatter(x, y, scatter_kwarg)
One possible solution I’m thinking is to have an unzip function that takes a dimention as an extra argument and returns an iterable of empty iterables with that size on the zero size case