Skip to content

Instantly share code, notes, and snippets.

@davepeck
Last active August 29, 2015 14:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save davepeck/017b15f10351f85f3428 to your computer and use it in GitHub Desktop.
Save davepeck/017b15f10351f85f3428 to your computer and use it in GitHub Desktop.
Random python iteration toy
def interleave(iterables, cmp=None, key=None, reverse=False):
"""
Given a collection of iterables, walk through them in
parallel, at each step yielding the current value
that comes first in the sort order, and advancing
that single iterator.
If each iterable is already sorted, this will produce
a total ordering. If not, it produces a 'greedy' ordering
>>> list(interleave([[1,2],[3,4]]))
[1,2,3,4]
>>> list(interleave([[1,2],[0,3]]))
[0,1,2,3]
>>> list(interleave([[1,2],[-1,-2]]))
[-1, -2, 1, 2]
"""
def _advance(iterator):
# I've never been happy with Python's
# use of exceptions for iteration
# control flow. Dangit.
try:
return (iterator.next(), False)
except StopIteration:
return (None, True)
# This code could certainly be more efficient,
# for example by maintaining a sorted array
# of current values and modifying it in place
# (probably using bisect); but is there a way
# to compress it more?
iterators = map(lambda i: i.__iter__(), iterables)
states = map(lambda i: [i, _advance(i)], iterators) # Each state is [iterator, (current_value, is_stopped)]
exhausted = reduce(lambda exhausted, state: exhausted and state[1][1], states, True)
while not exhausted:
available_states = filter(lambda state: not state[1][1], states)
sorted_states = sorted(available_states, cmp=cmp, key=lambda state: key(state[1][0]) if key else state[1][0], reverse=reverse)
chosen_state = sorted_states[0]
yield chosen_state[1][0]
chosen_state[1] = _advance(chosen_state[0])
exhausted = reduce(lambda exhausted, state: exhausted and state[1][1], states, True)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment