How to make heapq evaluate the heap off of a specific attribute?

后端 未结 7 714
野的像风
野的像风 2020-11-30 22:07

I wish to hold a heap of objects, not just numbers. They will have an integer attribute in them that the heap can sort by. The easiest way to use heaps in python is heapq,

相关标签:
7条回答
  • 2020-11-30 22:44

    I feel the simplest way is to override the existing cmp_lt function of the heapq module. A short example:

    import heapq
    
    # your custom function. Here, comparing tuples a and b based on their 2nd element
    def new_cmp_lt(self,a,b):
        return a[1]<b[1]
    
    #override the existing "cmp_lt" module function with your function
    heapq.cmp_lt=new_cmp_lt
    
    #Now use everything like normally used
    
    0 讨论(0)
  • 2020-11-30 22:45

    According to the example from the documentation, you can use tuples, and it will sort by the first element of the tuple:

    >>> h = []
    >>> heappush(h, (5, 'write code'))
    >>> heappush(h, (7, 'release product'))
    >>> heappush(h, (1, 'write spec'))
    >>> heappush(h, (3, 'create tests'))
    >>> heappop(h)
    (1, 'write spec')
    

    So if you don't want to (or can't?) do a __cmp__ method, you can manually extract your sorting key at push time.

    Note that if the first elements in a pair of tuples are equal, further elements will be compared. If this is not what you want, you need to ensure that each first element is unique.

    0 讨论(0)
  • 2020-11-30 22:48

    I had the same question but none of the above answers hit the spot although some were close but not elaborated enough. Anyway, I did some research and tried this piece of code and hopefully this should be sufficient for someone next who is looking to get an answer:

    The problem with using a tuple is it only uses the first item which is not very flexible. I wanted something similar to std::priority_queue in c++ like this: std::priority_queue<pair<int, int>, vector<pair<int, int>>, comparator> pq; where I could design my own comparator which is more common in real world applications.

    Hopefully the below snippet helps: https://repl.it/@gururajks/EvenAccurateCylinders

    import heapq
    class PQNode:
    
        def __init__(self, key, value):
            self.key = key
            self.value = value
    
        # compares the second value
        def __lt__(self, other):
            return self.value < other.value
    
        def __str__(self):
            return str("{} : {}".format(self.key, self.value))
    
    input = [PQNode(1, 4), PQNode(7, 4), PQNode(6, 9), PQNode(2, 5)]
    hinput = []
    for item in input:
        heapq.heappush(hinput, item)
    
    while (hinput):
        print (heapq.heappop(hinput))
    
    0 讨论(0)
  • 2020-11-30 22:50

    You could implement a heapdict. Note the use of popitem() to get the lowest priority item.

    import heapdict as hd
    import string
    import numpy as np
    
    h = hd.heapdict()
    keys = [char for char in string.ascii_lowercase[:10]]
    vals = [i for i in np.random.randint(0,10, 10)]
    for k,v in zip(keys,vals):
        h[k] = v
    for i in range(len(vals)):
        print h.popitem()
    
    0 讨论(0)
  • 2020-11-30 22:51

    heapq sorts objects the same way list.sort does, so just define a method __cmp__() within your class definition, which will compare itself to another instance of the same class:

    def __cmp__(self, other):
        return cmp(self.intAttribute, other.intAttribute)
    

    Works in Python 2.x.

    In 3.x use:

    def __lt__(self, other):
        return self.intAttribute < other.intAttribute
    
    0 讨论(0)
  • 2020-11-30 22:53

    According to the Official Document, a solution to this is to store entries as tuples (please take a look at Section 8.4.1 and 8.4.2).

    For example, your object is something like this in tuple's format (key, value_1, value_2)

    When you put the objects (i.e. tuples) into heap, it will take the first attribute in the object (in this case is key) to compare. If a tie happens, the heap will use the next attribute (i.e. value_1) and so on.

    For example:

    import heapq
    
    heap = []
    heapq.heappush(heap, (0,'one', 1))
    heapq.heappush(heap, (1,'two', 11))
    heapq.heappush(heap, (1, 'two', 2))
    heapq.heappush(heap, (1, 'one', 3))
    heapq.heappush(heap, (1,'two', 3))
    heapq.heappush(heap, (1,'one', 4))
    heapq.heappush(heap, (1,'two', 5))
    heapq.heappush(heap, (1,'one', 1))
    
    show_tree(heap)
    

    Output:

                                          (0, 'one', 1)                                       
                    (1, 'one', 1)                                (1, 'one', 4)                
        (1, 'one', 3)         (1, 'two', 3)         (1, 'two', 2)         (1, 'two', 5)     
    (1, 'two', 11)
    

    About pretty print a heap in python (updated the link): show_tree()

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