我想使用一个PriorityQueue,我需要添加一个类的对象(比如节点),我不能修改。我需要这些对象的优先级基于对象的字段。
我试着将它们作为元组(瓦尔,node)添加到队列中,但它仍然给我“TypeError:“Node”和“Node”的示例之间不支持“〈”“。它仍比较”node“对象以解析关系。
a = Node(3)
b = Node(4)
q = queue.PriorityQueue()
q.put(a)
q.put(b) // Errors TypeError: '<' not supported between instances of 'Node' and 'Node'
q.put((a.val, a))
q.put((b.val, b)) // Errors TypeError: '<' not supported between instances of 'Node' and 'Node'
我知道这个错误的原因是Node对象需要相互比较,根据文档,实现这个目的的方法是至少为Node实现lt和eq方法。https://docs.python.org/3.1/library/stdtypes.html#comparisons。
但是对于我的问题,由于我不能修改Node类,我是否能够向PriorityQueue传递一种方法(lambda或Comparator)以帮助它确定排序(我期待类似Java的东西)。q = PriorityQueue(comparator)
任何实现这一点的替代方案也是值得赞赏的。(记住节点是不可修改的)
2条答案
按热度按时间emeijp431#
一种解决方案是不传递比较器,将Node对象 Package 在另一个对象中,比如
ComparableNode
,它实现了您希望在Node
对象上进行的比较。假设您有以下设置:
但是你不能修改
Node
,所以你可以把它 Package 在你创建的类里。或者如果只想传递已经存在的
Node
对象:然后正常添加:
另一种方法是,在推入每个元素时指定其优先级。例如,heapq就是这样。
使用heapq时:
对于
queue.PriorityQueue
,请按照文档的建议使用元组如果有重复值,则比较将查看元组的第二个元素,并且由于
Node
不可比较而中断。在这种情况下,这取决于处理重复值的方式。如果要在出现重复值时保留插入顺序,可以执行以下操作:在heapq中也是如此,您可以很容易地将此行为 Package 在一个小函数中,这样就可以减少重复。
vvppvyoh2#
PriorityQueue
类不允许使用key
参数,但是您可以将其子类化,以隐式地将每个项 Package 在一个比较器对象(这里称为_Wrapper
)中。用法
下面是颠倒元素顺序的优先级队列的示例。
如果需要比较器而不是键,可以使用
functools.cmp_to_key
帮助器。