Merge sorted lists in python

前端 未结 9 982
花落未央
花落未央 2020-12-19 00:50

I have a bunch of sorted lists of objects, and a comparison function

class Obj :
    def __init__(p) :
        self.points = p
def cmp(a, b) :
    return a.p         


        
相关标签:
9条回答
  • 2020-12-19 00:55

    I asked a similar question and got some excellent answers:

    • Joining a set of ordered-integer yielding Python iterators

    The best solutions from that question are variants of the merge algorithm, which you can read about here:

    • Wikipedia: Merge Algorithm
    0 讨论(0)
  • 2020-12-19 00:56

    Use the bisect module. From the documentation: "This module provides support for maintaining a list in sorted order without having to sort the list after each insertion."

    import bisect
    
    def magic(*args):
        r = []
        for a in args:
            for i in a:
                bisect.insort(r, i)
        return r
    
    0 讨论(0)
  • 2020-12-19 01:07

    Here you go: a fully functioning merge sort for lists (adapted from my sort here):

    def merge(*args):
        import copy
        def merge_lists(left, right):
            result = []
            while left and right:
                which_list = (left if left[0] <= right[0] else right)
                result.append(which_list.pop(0))
            return result + left + right
        lists = list(args)
        while len(lists) > 1:
            left, right = copy.copy(lists.pop(0)), copy.copy(lists.pop(0))
            result = merge_lists(left, right)
            lists.append(result)
        return lists.pop(0)
    

    Call it like this:

    merged_list = merge(a, b, c)
    for item in merged_list:
        print item
    

    For good measure, I'll throw in a couple of changes to your Obj class:

    class Obj(object):
        def __init__(self, p) :
            self.points = p
        def __cmp__(self, b) :
            return cmp(self.points, b.points)
        def __str__(self):
            return "%d" % self.points
    
    • Derive from object
    • Pass self to __init__()
    • Make __cmp__ a member function
    • Add a str() member function to present Obj as string
    0 讨论(0)
  • 2020-12-19 01:11

    Instead of using a list, you can use a [heap](http://en.wikipedia.org/wiki/Heap_(data_structure).

    The insertion is O(log(n)), so merging a, b and c will be O(n log(n))

    In Python, you can use the heapq module.

    0 讨论(0)
  • 2020-12-19 01:14

    One line solution using sorted:

    def magic(*args):
      return sorted(sum(args,[]), key: lambda x: x.points)
    

    IMO this solution is very readable.

    Using heapq module, it could be more efficient, but I have not tested it. You cannot specify cmp/key function in heapq, so you have to implement Obj to be implicitly sorted.

    import heapq
    def magic(*args):
      h = []
      for a in args:
        heapq.heappush(h,a)
      return [i for i in heapq.heappop(h)
    
    0 讨论(0)
  • 2020-12-19 01:15

    I don't know whether it would be any quicker, but you could simplify it with:

    def GetObjKey(a):
        return a.points
    
    return sorted(a + b + c, key=GetObjKey)
    

    You could also, of course, use cmp rather than key if you prefer.

    0 讨论(0)
提交回复
热议问题