heapreplace(a, x) returns the smallest value originally in a regardless of the value of x, while, as the name suggests, heappushpop(a, x) pushes x onto a before popping the smallest value. Using your data, here's a sequence that shows the difference:
>>> from heapq import *
>>> a = [2,7,4,0,8,12,14,13,10,3,4]
>>> heapify(a)
>>> b = a[:]
>>> heappushpop(a, -1)
-1
>>> heapreplace(b, -1)
0
Answer from Tim Peters on Stack Overflowheap - python, heapq: difference between heappushpop() and heapreplace() - Stack Overflow
python - How to efficiently pop all elements with the smallest key in heapq? - Stack Overflow
How to use Python's heapq as min-heap AND max-heap?
python - How to make heapq evaluate the heap off of a specific attribute? - Stack Overflow
Videos
heapreplace(a, x) returns the smallest value originally in a regardless of the value of x, while, as the name suggests, heappushpop(a, x) pushes x onto a before popping the smallest value. Using your data, here's a sequence that shows the difference:
>>> from heapq import *
>>> a = [2,7,4,0,8,12,14,13,10,3,4]
>>> heapify(a)
>>> b = a[:]
>>> heappushpop(a, -1)
-1
>>> heapreplace(b, -1)
0
in many common cases the ultimate result seems the same, but the process and behavior is different, and can be visible in corner cases:
heappushpop() is equivalent to pushing first, then popping, meaning, amongst other things, that your heap size might change in the process (and that, for example, if your heap is empty you'll get back the element you pushed).
heapreplace() is equivalent to popping first, then pushing, with the additional restriction of guaranteeing that your heap size won't change in the process. this means you'll get an error on an empty heap, amongst other interesting corner behaviour.
The general technique you show is the most efficient as well as being straightforward. But you're doing extra assignments that aren't really necessary. Below is a minor optimization.
elements = []
k1, v1 = heapq.heappop(heap)
elements.append((k1,v1))
while(k1 == heap[0]):
k2, v2 = heapq.heappop(heap)
elements.append((k2,v2))
return elements
To be on the safe side, you probably should add checks to make sure your heap isn't empty. Checking heap[0] when there are no items in the heap would be a bad thing, as would calling heapq.heappop if the heap is empty.
I was going to suggest a change of structure from a heap of (k, v) to a heap of k and a dictionary of {k:[v]}. This would turn your code into:
k = heap[0]
return [(k,v) for v in hash[k]]
With:
hash = defaultdict(list)
heap = []
heappush(heap, (k, v)) would become:
heappush(heap, k)
hash[k].append(v)
heappop(heap) would become:
k = heappop(heap)
v = hash[k].pop()
I know that heapq in python is min-heap (first element is the smallest).
How do I initialize a max-heap, where the root is the largest?
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.
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