【发布时间】:2018-07-18 08:30:29
【问题描述】:
我将一个名为 UNVISITED 的空列表转换为一个堆,这样:
UNVISITED = []
heapq.heappush(UNVISITED, (a.f, a))
我推送的对象a,是从一个类中实例化的,有以下字段:
class UNVISITEDNode():
def __init__(self, value1, value2 , value3, value4, value5):
self.q = value1
self.h = value2
self.g = value3
self.f = value4
self.p = value5
在我的算法中,我会在需要时不断修改堆中已经存在的对象中的任何valueX,例如:
for i in range(len(UNVISITED)):
UNVISITED[i][1].q = newvalue1
UNVISITED[i][1].h = newvalue2
UNVISITED[i][1].g = newvalue3
UNVISITED[i][1].f = newvalue4
UNVISITED[i][1].p = newvalue5
因为(或者我认为,如果我错了请纠正我)像我现在所做的那样修改值f不会改变影响堆排序的值,我直接尝试修改UNVISITED[i][0] (即上面的a.f 在创建堆时作为第二个参数的第二部分传递)。
[THE PROBLEM] -> 然后我被告知这个值不允许修改:
UNVISITED[i][0] = newvalue4
*Traceback (most recent call last):
File "/home/daniel/pycharm-2017.3.3/helpers/pydev/
_pydevd_bundle/pydevd_exec.py", line 3, in Exec
exec exp in global_vars, local_vars
File "<input>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
我确实需要修改对象a的值f,每次需要都会影响堆的排序,你不能通过UNVISITED[i][1].f = newvalue4来做到这一点(显然)强>。有没有办法做到这一点或任何解决方法?
编辑(已解决)
最终,我将一个简单的手动堆定义为 heap = [] 和 heap.append() 的对象。
您可以使用heap.pop() 弹出堆中的第一个元素,并使用heap.sort(key=lambda x: x.f, reverse=True) 根据属性值对其进行排序。
像这样,您将更接近heapq 的行为,并且您可以修改堆中的元素,该堆为其排序。
重要的是要说这比使用heapq 慢得多。
尽管如此,我将@Raymong Hettinger 的答案标记为好的答案,因为其他可能的变通方法的详细信息。
此外,@Davis Yoshida 提出了一个有效的观点,即定义的 堆 可能不是存储数据的最佳方式。
【问题讨论】:
-
代码中的其他地方可能存在错误,您无意中将元组分配给
UNVISITED[i][0]而不仅仅是UNVISITED[i]。 -
@chepner 我是故意这样做的,因此根据
UNVISITED[i][0]中的值对堆进行排序。你可以在这篇文章的第一行看到这一点。如果您还想弹出其他内容,Afaik 是一种定义它的方法。