Perform an N-way merge operation on sorted lists. @param list_of_lists: (really iterable of iterable) of sorted elements (either by naturally or by C{key}) @param key: specify sort key function (like C{sort()}, C{sorted()}) @param iterfun: function that returns an iterator. Yi
(list_of_lists, key=None)
| 1 | import heapq |
| 2 | def mergesort(list_of_lists, key=None): |
| 3 | """ Perform an N-way merge operation on sorted lists. |
| 4 | |
| 5 | @param list_of_lists: (really iterable of iterable) of sorted elements |
| 6 | (either by naturally or by C{key}) |
| 7 | @param key: specify sort key function (like C{sort()}, C{sorted()}) |
| 8 | @param iterfun: function that returns an iterator. |
| 9 | |
| 10 | Yields tuples of the form C{(item, iterator)}, where the iterator is the |
| 11 | built-in list iterator or something you pass in, if you pre-generate the |
| 12 | iterators. |
| 13 | |
| 14 | This is a stable merge; complexity O(N lg N) |
| 15 | |
| 16 | Examples:: |
| 17 | |
| 18 | print list(x[0] for x in mergesort([[1,2,3,4], |
| 19 | [2,3.5,3.7,4.5,6,7], |
| 20 | [2.6,3.6,6.6,9]])) |
| 21 | [1, 2, 2, 2.6, 3, 3.5, 3.6, 3.7, 4, 4.5, 6, 6.6, 7, 9] |
| 22 | |
| 23 | # note stability |
| 24 | print list(x[0] for x in mergesort([[1,2,3,4], |
| 25 | [2,3.5,3.7,4.5,6,7], |
| 26 | [2.6,3.6,6.6,9]], key=int)) |
| 27 | [1, 2, 2, 2.6, 3, 3.5, 3.6, 3.7, 4, 4.5, 6, 6.6, 7, 9] |
| 28 | |
| 29 | print list(x[0] for x in mergesort([[4,3,2,1], |
| 30 | [7,6.5,4,3.7,3.3,1.9], |
| 31 | [9,8.6,7.6,6.6,5.5,4.4,3.3]], |
| 32 | key=lambda x: -x)) |
| 33 | [9, 8.6, 7.6, 7, 6.6, 6.5, 5.5, 4.4, 4, 4, 3.7, 3.3, 3.3, 3, 2, 1.9, 1] |
| 34 | |
| 35 | |
| 36 | """ |
| 37 | |
| 38 | heap = [] |
| 39 | for i, itr in enumerate(iter(pl) for pl in list_of_lists): |
| 40 | try: |
| 41 | item = itr.next() |
| 42 | toadd = (key(item), i, item, itr) if key else (item, i, itr) |
| 43 | heap.append(toadd) |
| 44 | except StopIteration: |
| 45 | pass |
| 46 | heapq.heapify(heap) |
| 47 | |
| 48 | if key: |
| 49 | while heap: |
| 50 | _, idx, item, itr = heap[0] |
| 51 | yield item, itr |
| 52 | try: |
| 53 | item = itr.next() |
| 54 | heapq.heapreplace(heap, (key(item), idx, item, itr) ) |
| 55 | except StopIteration: |
| 56 | heapq.heappop(heap) |
| 57 | |
| 58 | else: |
| 59 | while heap: |
| 60 | item, idx, itr = heap[0] |