Según la documentación de heapq , la forma de personalizar el orden del montón es hacer que cada elemento del montón sea una tupla, siendo el primer elemento de tupla uno que acepte las comparaciones normales de Python.
Las funciones en el módulo heapq son un poco engorrosas (ya que no están orientadas a objetos), y siempre requieren que nuestro objeto de pila (una lista en pila) se pase explícitamente como primer parámetro. Podemos matar dos pájaros de un tiro creando una clase contenedora muy simple que nos permitirá especificar unkey
función y presentar el montón como un objeto.
La siguiente clase mantiene una lista interna, donde cada elemento es una tupla, el primer miembro de la cual es una clave, calculada en el momento de la inserción del elemento usando el key
parámetro, pasado en la instanciación de Heap:
import heapq
class MyHeap(object):
def __init__(self, initial=None, key=lambda x:x):
self.key = key
self.index = 0
if initial:
self._data = [(key(item), i, item) for i, item in enumerate(initial)]
self.index = len(self._data)
heapq.heapify(self._data)
else:
self._data = []
def push(self, item):
heapq.heappush(self._data, (self.key(item), self.index, item))
self.index += 1
def pop(self):
return heapq.heappop(self._data)[2]
(La self.index
parte adicional es evitar conflictos cuando el valor clave evaluado es un empate y el valor almacenado no es directamente comparable; de lo contrario, heapq podría fallar con TypeError)