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[0]), list(first_second[1])) 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[0]), list(xy[1])) 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