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, but how do I tell it to sort by a specific attribute when using heapq?
Unfortunately, you can't, although this is an often requested feature.
One option would be to insert (key, value) tuples into the heap. However, that won't work if the values throw an exception when compared (they will be compared in the case of a tie between keys).
A second option would be to define a __lt__
(less-than) method in the class that will use the appropriate attribute to compare the elements for sorting. However, that might not be possible if the objects were created by another package or if you need them to compare differently elsewhere in the program.
A third option would be to use the sortedlist class from the blist module (disclaimer: I'm the author). The constructor for sortedlist
takes a key
parameter that lets you specify a function to return the sort key of an element, similar to the key
parameter of list.sorted
and sorted
.
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
According to 8.4.1 of http://docs.python.org/library/heapq.html, 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.