How can I remove an arbitrary item from a priority queue. Suppose I have a PriorityQueue for jobs. I have a job I want to "cancel" so I need to remove it from the queue, how can I do that?
UPDATE
To add to the answer, a related question: https://stackoverflow.com/a/9288081/292291
The remove () method of PriorityQueue class removes a single instance of the specified element from this queue, only if it is present. o - It is the element to be eliminated from this queue.
Priority Queue is an extension of queue with following properties. 1) Every item has a priority associated with it. 2) An element with high priority is dequeued before an element with low priority. 3) If two elements have the same priority, they are served according to their order in the queue.
Geek, have you ever wondered what will happen if calls of remove () method exceed the elements present in the queue. In this scenario, it will continue to remove the elements that were there, and thereafter it will not find any element to remove priority-wise, so it will throw an exception which is as follows.
Every item has a priority associated with it. An element with high priority is dequeued before an element with low priority. If two elements have the same priority, they are served according to their order in the queue.
I'm assuming you're using heapq
. The documentation has this to say about this problem, which seems quite reasonable:
The remaining challenges revolve around finding a pending task and making changes to its priority or removing it entirely. Finding a task can be done with a dictionary pointing to an entry in the queue.
Removing the entry or changing its priority is more difficult because it would break the heap structure invariants. So, a possible solution is to mark the existing entry as removed and add a new entry with the revised priority.
The documentation provides some basic example code to show how this can be done, which I reproduce here verbatim:
pq = [] # list of entries arranged in a heap
entry_finder = {} # mapping of tasks to entries
REMOVED = '<removed-task>' # placeholder for a removed task
counter = itertools.count() # unique sequence count
def add_task(task, priority=0):
'Add a new task or update the priority of an existing task'
if task in entry_finder:
remove_task(task)
count = next(counter)
entry = [priority, count, task]
entry_finder[task] = entry
heappush(pq, entry)
def remove_task(task):
'Mark an existing task as REMOVED. Raise KeyError if not found.'
entry = entry_finder.pop(task)
entry[-1] = REMOVED
def pop_task():
'Remove and return the lowest priority task. Raise KeyError if empty.'
while pq:
priority, count, task = heappop(pq)
if task is not REMOVED:
del entry_finder[task]
return task
raise KeyError('pop from an empty priority queue')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With