Just found out about this cool feature in the Python standard library that allows you to merge two iterables based on a comparison:
from heapq import merge as merge_heapwise
some_numbers = (1, 5, 10, 15)
other_numbers = (2, 4, 6, 8, 10, 12, 14, 16)
merged_numbers = tuple(merge_heapwise(some_numbers, other_numbers)) # Using a tuple so comparisons work, for didactic demo reasons
assert merged_numbers == (1, 2, 4, 5, 6, 8, 10, 12, 14, 15, 16)
It's lazy, so you can use it for merging unbounded streams, though beware it could be considered "slightly destructive": it'll be internally "hoarding" 1 item from each iterable it didn't yield from that iteration (obviously, this is necessarily a part of the design, since it's got to have both items before it can compare them.) It supports an arbitrary number of input iterables.
It supports parameter key
, so you can specify some pre-comparison interpretation of the elements you're merging (such as key=lambda e: float(e.get('x'))
, which I just recently used to merge two streams of SVG element generators into a reasonable order for rendering.)
It isn't really fully general; unless you wanted to make a wrapper class overriding the behavior of the comparison operators, you can't use an arbitrary function for deciding which element this function yields; however, for my use-case, it was pretty handy to have this function pre-written in the standard library.