Proposal:
I propose to add an optional argument to the pairwise
function in the itertools
module. When this argument is set to True
, the iterator returned by pairwise
should include a pair of the last and the first element of the input iterator (if the input iterator is finite).
I also suggest circular
as the name for this argument.
Example:
>>> list(pairwise(['A', 'B', 'C', 'D'], circular = True))
[('A', 'B'), ('B', 'C'), ('C', 'D'), ('D', 'A')]
Why?
I found this extension of pairwise
to be useful when working with geometrical shapes, specifically polygons. When corners
is the (ordered) list of corners of a polygon, pairwise(corners, circular = True)
can be used to iterate over the edges of that polygon.
There are likely some other cases in which this can be useful, for example creating secret santa pairs or something of that kind, or more generally when working with circular linked list data structures.
Reference implementation:
from itertools import tee, chain
def pairwise(iterable, circular = False):
a, b = tee(iterable)
first = next(b, None)
return zip(a, chain(b, [first] if circular else []))
Edge cases:
>>> list(pairwise(['A'], circular = True))
[('A', 'A')]
>>> list(pairwise([], circular = True))
[]