# [Baypiggies] a python puzzle

Damon McCormick damonmc at gmail.com
Wed Apr 14 18:29:08 CEST 2010

```Keeping your original approach, you could define a function like this:

def next_or_none_pair (itr):
def result_func ():
try:
return itr.next()
except StopIteration:
return (None, None)
return result_func

and then replace your current definitions of xnext and ynext by the
following:

xnext = next_or_none_pair(itertools.groupby(xs, grouper))
ynext = next_or_none_pair(itertools.groupby(ys, grouper))

The condition of your while loop is already set up to exit when either x or
y is None (a condition which, I believe, is currently never True, since the
loop ends when StopIteration is thrown).

So the only other modification you'd need is that your comparisions between
x and y need to handle None:

elif y is None or x < y:
yield list(xgroup), None
x, xgroup = xnext()
elif x is None or x > y:
yield (None, list(ygroup))
y, ygroup = ynext()

So the entire thing would look like this:

import itertools

def next_or_none_pair (itr):
def result_func ():
try:
return itr.next()
except StopIteration:
return (None, None)
return result_func

def as_pairs (xs, ys, grouper=lambda _: _):

"""
>>> aordered = [1, 1, 2, 4, 6, 8,
9]
>>> bordered = [1, 3, 4, 5, 6, 7,
8]
>>> for a, b in as_pairs(aordered,
bordered):
... a,
b
([1, 1],
[1])
([2],
None)
(None,
[3])
([4],
[4])
(None,
[5])
([6],
[6])
(None,
[7])
([8],
[8])
([9],
None)
"""
# assume xs and ys are
sorted.
xnext = next_or_none_pair(itertools.groupby(xs, grouper))
ynext = next_or_none_pair(itertools.groupby(ys, grouper))
import itertools

def next_or_none_pair (itr):
def result_func ():
try:
return itr.next()
except StopIteration:
return (None, None)
return result_func

def as_pairs (xs, ys, grouper=lambda _: _):

"""
>>> aordered = [1, 1, 2, 4, 6, 8,
9]
>>> bordered = [1, 3, 4, 5, 6, 7,
8]
>>> for a, b in as_pairs(aordered,
bordered):
... a,
b
([1, 1],
[1])
([2],
None)
(None,
[3])
([4],
[4])
(None,
[5])
([6],
[6])
(None,
[7])
([8],
[8])
([9],
None)
"""
# assume xs and ys are
sorted.
xnext = next_or_none_pair(itertools.groupby(xs, grouper))
ynext = next_or_none_pair(itertools.groupby(ys, grouper))
x, xgroup = xnext()
y, ygroup = ynext()
while x or y:
if x == y:
yield list(xgroup), list(ygroup)
x, xgroup = xnext()
y, ygroup = ynext()
elif y is None or x < y:
yield list(xgroup), None
x, xgroup = xnext()
elif x is None or x > y:
yield (None, list(ygroup))
y, ygroup = ynext()
else:
assert False

if __name__ == "__main__":
import doctest
doctest.testmod()

On Wed, Apr 14, 2010 at 9:04 AM, Brent Pedersen <bpederse at gmail.com> wrote:

> On Wed, Apr 14, 2010 at 8:20 AM, Brent Pedersen <bpederse at gmail.com>
> wrote:
> > hi, in trying to write a func that does a kind of merging of 2 sorted
> lists,
> > i've come up with a fairly simple implementation that "almost works":
> > http://gist.github.com/365485
> >
> > but it hits StopIteration before returning the last value ([9], None)
> > i can wrap the whole thing in a bunch more if statements, i've tried
> > heapq.merge, but cant find a nice solution.
> >
> > any ideas? i think it's an interesting problem.
> > -brent
> >
>
> i should add the for my real use-case, the iterables going in will not
> be lists, they'll be lazily generated, and very large, so
> i dont want to read them into memory to get the last element or slice them.
> ______________________________
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/baypiggies/attachments/20100414/20438e1b/attachment.html>
```