Python的heapq使用自定义比较predicate自定义、Python、heapq、predicate

2023-09-11 01:45:17 作者:凝眸温暖我心

我想建立一个自定义排序predicate堆。由于这些值进入它的用户自定义类型的,我不能修改其内置的比较predicate。

I am trying to build a heap with a custom sort predicate. Since the values going into it are of 'user-defined' type, I cannot modify their built-in comparison predicate.

有没有办法做这样的事情:

Is there a way to do something like:

h = heapq.heapify([...], key=my_lt_pred)
h = heapq.heappush(h, key=my_lt_pred)

甚至更好,我可以换我自己的容器中heapq功能,所以我并不需要不断传递predicate。

Or even better, I could wrap the heapq functions in my own container so I don't need to keep passing the predicate.

推荐答案

按照 heapq文档中,方式来定制堆顺序是有对堆的每个元素是一个元组,与第一元组元件是一个接受正常的Python比较

According to the heapq documentation, the way to customize the heap order is to have each element on the heap to be a tuple, with the first tuple element being one that accepts normal Python comparisons.

在heapq模块中的功能是有点麻烦(因为它们不是面向对象的),始终要求我们的堆对象(一heapified清单)进行显式传递作为第一个参数。我们可以一举两得一石创建一个非常简单的包装类,它将使我们能够指定一个函数,present堆作为对象。

The functions in the heapq module are a bit cumbersome (since they are not object-oriented), and always require our heap object (a heapified list) to be explicitly passed as the first parameter. We can kill two birds with one stone by creating a very simple wrapper class that will allow us to specify a key function, and present the heap as an object.

类下面保持一个内部列表,其中每个元素都是一个元组,第一个部件,它是一个关键,计算元素的插入时间使用参数,在堆实例通过:

The class below keeps an internal list, where each element is a tuple, the first member of which is a key, calculated at element insertion time using the key parameter, passed at Heap instantiation:

# -*- coding: utf-8 -*-
import heapq

class MyHeap(object):
   def __init__(self, initial=None, key=lambda x:x):
       self.key = key
       if initial:
           self._data = [(key(item), item) for item in initial]
           heapq.heapify(self._data)
       else:
           self._data = []

   def push(self, item):
       heapq.heappush(self._data, (self.key(item), item))

   def pop(self):
       return heapq.heappop(self._data)[1]