Re: [Python-ideas] Rewriting the "roundrobin" recipe in the itertools documentation

def roundrobin(*iterables): "roundrobin('ABC', 'D', 'EF') --> A D E B F C" nexts = [ iter(it).__next__ for it in iterables ] i = 0 while nexts: i %= len(nexts) try: yield nexts[i]() except StopIteration: del nexts[i] else: i += 1 Regards Alon Snir

Here's toolz.itertoolz.interleave(): def interleave(seqs): """ Interleave a sequence of sequences >>> list(interleave([[1, 2], [3, 4]])) [1, 3, 2, 4] >>> ''.join(interleave(('ABC', 'XY'))) 'AXBYC' Both the individual sequences and the sequence of sequences may be infinite Returns a lazy iterator """ iters = itertools.cycle(map(iter, seqs)) while True: try: for itr in iters: yield next(itr) return except StopIteration: predicate = partial(operator.is_not, itr) iters = itertools.cycle(itertools.takewhile(predicate, iters)) At first glance, map should be e.g. six.moves.map for pythonic backward compatibility. Is this slower than the linear time implementations listed here? On Tuesday, November 21, 2017, Alon Snir <AlonSnir@hotmail.com> wrote:

It would be faster with ‘deque’: def roundrobin(*iterables): iters = deque(map(iter,iterables), len(iterables)) while iters: try: yield next(iters[0]) except StopIteration: iters.popleft() else: iters.rotate(-1) From: Wes Turner [mailto:wes.turner@gmail.com] Sent: Wednesday, November 22, 2017 04:11 To: Alon Snir <AlonSnir@hotmail.com> Cc: python-ideas@python.org Subject: Re: [Python-ideas] Rewriting the "roundrobin" recipe in the itertools documentation Here's toolz.itertoolz.interleave(): def interleave(seqs): """ Interleave a sequence of sequences >>> list(interleave([[1, 2], [3, 4]])) [1, 3, 2, 4] >>> ''.join(interleave(('ABC', 'XY'))) 'AXBYC' Both the individual sequences and the sequence of sequences may be infinite Returns a lazy iterator """ iters = itertools.cycle(map(iter, seqs)) while True: try: for itr in iters: yield next(itr) return except StopIteration: predicate = partial(operator.is_not, itr) iters = itertools.cycle(itertools.takewhile(predicate, iters)) At first glance, map should be e.g. six.moves.map for pythonic backward compatibility. Is this slower than the linear time implementations listed here? On Tuesday, November 21, 2017, Alon Snir <AlonSnir@hotmail.com<mailto:AlonSnir@hotmail.com>> wrote: def roundrobin(*iterables): "roundrobin('ABC', 'D', 'EF') --> A D E B F C" nexts = [ iter(it).__next__ for it in iterables ] i = 0 while nexts: i %= len(nexts) try: yield nexts[i]() except StopIteration: del nexts[i] else: i += 1 Regards Alon Snir _______________________________________________ Python-ideas mailing list Python-ideas@python.org<javascript:;> https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/

On Wed, Nov 22, 2017 at 11:28:20AM +0000, Alon Snir wrote:
It would be faster with ‘deque’:
It isn't. According to my testing, your version with deque is approximately two times slower than the version from toolz.itertoolz that Wes quotes. -- Steve

Here's toolz.itertoolz.interleave(): def interleave(seqs): """ Interleave a sequence of sequences >>> list(interleave([[1, 2], [3, 4]])) [1, 3, 2, 4] >>> ''.join(interleave(('ABC', 'XY'))) 'AXBYC' Both the individual sequences and the sequence of sequences may be infinite Returns a lazy iterator """ iters = itertools.cycle(map(iter, seqs)) while True: try: for itr in iters: yield next(itr) return except StopIteration: predicate = partial(operator.is_not, itr) iters = itertools.cycle(itertools.takewhile(predicate, iters)) At first glance, map should be e.g. six.moves.map for pythonic backward compatibility. Is this slower than the linear time implementations listed here? On Tuesday, November 21, 2017, Alon Snir <AlonSnir@hotmail.com> wrote:

It would be faster with ‘deque’: def roundrobin(*iterables): iters = deque(map(iter,iterables), len(iterables)) while iters: try: yield next(iters[0]) except StopIteration: iters.popleft() else: iters.rotate(-1) From: Wes Turner [mailto:wes.turner@gmail.com] Sent: Wednesday, November 22, 2017 04:11 To: Alon Snir <AlonSnir@hotmail.com> Cc: python-ideas@python.org Subject: Re: [Python-ideas] Rewriting the "roundrobin" recipe in the itertools documentation Here's toolz.itertoolz.interleave(): def interleave(seqs): """ Interleave a sequence of sequences >>> list(interleave([[1, 2], [3, 4]])) [1, 3, 2, 4] >>> ''.join(interleave(('ABC', 'XY'))) 'AXBYC' Both the individual sequences and the sequence of sequences may be infinite Returns a lazy iterator """ iters = itertools.cycle(map(iter, seqs)) while True: try: for itr in iters: yield next(itr) return except StopIteration: predicate = partial(operator.is_not, itr) iters = itertools.cycle(itertools.takewhile(predicate, iters)) At first glance, map should be e.g. six.moves.map for pythonic backward compatibility. Is this slower than the linear time implementations listed here? On Tuesday, November 21, 2017, Alon Snir <AlonSnir@hotmail.com<mailto:AlonSnir@hotmail.com>> wrote: def roundrobin(*iterables): "roundrobin('ABC', 'D', 'EF') --> A D E B F C" nexts = [ iter(it).__next__ for it in iterables ] i = 0 while nexts: i %= len(nexts) try: yield nexts[i]() except StopIteration: del nexts[i] else: i += 1 Regards Alon Snir _______________________________________________ Python-ideas mailing list Python-ideas@python.org<javascript:;> https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/

On Wed, Nov 22, 2017 at 11:28:20AM +0000, Alon Snir wrote:
It would be faster with ‘deque’:
It isn't. According to my testing, your version with deque is approximately two times slower than the version from toolz.itertoolz that Wes quotes. -- Steve
participants (3)
-
Alon Snir
-
Steven D'Aprano
-
Wes Turner