def leftjoin(left_stream, right_stream, key=(lambda x: x), unused=None):
 left_stream = iter(left_stream)
 right_stream = iter(right_stream)
 try:
  right = next(right_stream)
  for left in left_stream:
   while (right and (key(left) > key(right))):
    if (unused is not None):
     unused(right)
    right = next(right_stream)
   if (key(left) == key(right)):
    (yield (left, right))
    del left
    right = next(right_stream)
   else:
    (yield (left, None))
 except StopIteration:
  try:
   (yield (left, None))
  except NameError:
   pass
  for left in left_stream:
   (yield (left, None))
 else:
  if (unused is not None):
   try:
    unused(right)
   except NameError:
    pass
   for right in right_stream:
    unused(right)

def leftjoin ( left_stream , right_stream , key = ( lambda x : x ) , unused = None ) : left_stream = iter ( left_stream ) right_stream = iter ( right_stream ) try : right = next ( right_stream ) for left in left_stream : while ( right and ( key ( left ) > key ( right ) ) ) : if ( unused is not None ) : unused ( right ) right = next ( right_stream ) if ( key ( left ) == key ( right ) ) : ( yield ( left , right ) ) del left right = next ( right_stream ) else : ( yield ( left , None ) ) except StopIteration : try : ( yield ( left , None ) ) except NameError : pass for left in left_stream : ( yield ( left , None ) ) else : if ( unused is not None ) : try : unused ( right ) except NameError : pass for right in right_stream : unused ( right )
a "left join" operation on sorted iterators yields pairs .