【问题标题】:Check if heapq contains value检查 heapq 是否包含值
【发布时间】:2014-10-08 14:45:47
【问题描述】:

我正在使用 heapq 对象来存储我实现的类的对象。

import heapq

heap = []
element1 = Element('A', 1)
element2 = Element('B', 2)
element3 = Element('C', 3)
heapq.heappush(heap, element1)
heapq.heappush(heap, element2)
heapq.heappush(heap, element3)

在我的类 Element 中,我覆盖方法 __cmp__ 以确保值是优先级

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

现在我想写一个函数,它检查堆是否包含元素,这样 如果我想检查element = Element('A', 1) 是否在堆中,答案将是True,如果我要检查element = Element('A',100),答案也将是True,但如果我想检查element = Element('D',1),答案将是是False。 我怎样才能实现这样的方法?是否可以在不调用pop() 方法的情况下检查heapq 的元素?

【问题讨论】:

  • Element 是否只是用于此堆的值及其优先级的包装器,还是出于其他原因必须使用此类?
  • 你能补充一点关于这个类的实际用途的信息吗?这是针对 python 2 还是 3 的?
  • @tobias_k 因为其他原因我不得不使用这个类
  • @Ziva 在这种情况下,您可以特别注意以不一致的方式实现eqcmp 不会在其他地方造成问题。

标签: python queue priority-queue


【解决方案1】:

Element 中添加__eq__ 方法,以便您可以使用关键字in 检查成员资格(如果没有__eq__,代码Element('A', 1) == Element('A', 1) 将给出False):

class Element:
    def __init__(self, key, value):
        self.key = key
        self.value = value

    def __eq__(self, other):
        return self.key == other.key

堆只是python中的列表,所以只需使用以下内容,__eq__ 将完成剩下的工作:

Element('A', 1) in heap

示例

import heapq

heap = []
element1 = Element('A', 1)
element2 = Element('B', 2)
element3 = Element('C', 3)
heapq.heappush(heap, element1)
heapq.heappush(heap, element2)
heapq.heappush(heap, element3)

print Element('A', 1) in heap      # True
print Element('A', 100) in heap    # True
print Element('D', 1) in heap      # False

【讨论】:

  • 我认为__eq__ 应该只比较key,所以(A, 1) == (A, 100)
  • @tobias_k 这是可能的,但也许他想允许重复,这取决于语义。让我们看看 OP 怎么说,如果需要,我会修改代码。感谢您的观察!
  • 我认为很清楚:“如果我检查 element = Element('A',100) 答案也是 True”
  • 哈哈抱歉;)谢谢
【解决方案2】:

solution by @enrico 起作用,实现__eq__ 来检查元素是否在堆中,并实现__cmp__ 来确定元素的优先级。但是,它会产生一些奇怪的副作用。例如,Element('A', 1) 将同时是 ==< 而不是 Element('A', 2)

或者,您可以只使用常规 tuples 而不是 Element 包装类。首先使用数字,元组自然排序就足够了堆,并且为了检查堆中是否有某个元素,您可以zip这些项目来获取实际键的列表(在您的示例中:字母)或使用any

heap = []
heapq.heappush(heap, (1, 'A'))
heapq.heappush(heap, (3, 'C'))
heapq.heappush(heap, (2, 'B'))

print('A' in zip(*heap)[1])
print(any('D' == b for a, b in heap)

输出:

True
False

但是请注意,(就像使用 __eq__in 一样)这将在最坏的情况下(元素不在堆中)测试堆中的每个元素,如果这是用于排序优先级队列设置,将破坏堆的 O(log n) 性能。相反,您可能希望在堆之外使用另一个 setdict 来存储和查找已处理(及其相应结果)和/或当前在堆中的元素。

【讨论】:

    猜你喜欢
    • 2019-01-04
    • 2017-06-04
    • 2019-08-10
    • 2020-10-08
    • 2013-05-28
    • 2015-01-01
    • 2021-07-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多