简体   繁体   English

如何在python中颠倒PriorityQueue的顺序?

[英]How do I reverse the order of PriorityQueue in python?

I have created a simple priority queue in python that orders items by their value:我在 python 中创建了一个简单的优先级队列,它按项目的值对项目进行排序:

import Queue
q = Queue.PriorityQueue()
for it in items:
    q.put((it.value, it))

but when i print the queue using:但是当我使用以下方法打印队列时:

while not q.empty()
    print q.get()

it will always print the lowest value first.它将始终首先打印最低值。 is there a way of getting the last item in a queue without changing the last two lines in the top bit of code to:有没有办法在不将代码顶部的最后两行更改为:

for it in items:
    q.put((-1*it.value, it))

because that seems a bit messy and creates problems if i want to use that information for something else (i would have to multiply it by -1 again)因为如果我想将该信息用于其他用途,这似乎有点混乱并且会产生问题(我必须再次将其乘以 -1)

You could just make your own class that inherits from PriorityQueue and does the messy -1 multiplication under the hood for you:可以创建自己的类,该类继承自 PriorityQueue 并在后台为您执行混乱的 -1 乘法:

class ReversePriorityQueue(PriorityQueue):

def put(self, tup):
    newtup = tup[0] * -1, tup[1]
    PriorityQueue.put(self, newtup)

def get(self):
    tup = PriorityQueue.get(self)
    newtup = tup[0] * -1, tup[1]
    return newtup

This appears to work with tuples, at least:这似乎适用于元组,至少:

Q = ReversePriorityQueue()

In [94]: Q.put((1,1))

In [95]: Q.get()
Out[95]: (1, 1)

In [96]: Q.put((1,1))

In [97]: Q.put((5,5))

In [98]: Q.put((9,9))

In [99]: Q.get()
Out[99]: (9, 9)

In [100]: Q.get()
Out[100]: (5, 5)

In [101]: Q.get()
Out[101]: (1, 1)

I'm sure you could generalize the code to work with more than just tuples from here.我相信您可以将代码概括为不仅可以使用这里的元组。

You can make the transformation transparent.您可以使转换透明。

What you want is to have a new q.get and a new q.put that transparently modifies data in and out of queue to reverse order:你想要的是有一个新的q.get和一个新的q.put透明地修改数据进出队列以颠倒顺序:

# new reversed priority put method
q.oldput = q.put
q.put = lambda p, i: q.oldput((p * -1, i))

# new reversed priority get method
q.oldget = q.get
# create get closure for queue
def newget(q):
    def g():
        item = q.oldget()
        # reverse first element
        return item[0] * -1, item[1]
    # return get method for given queue
    return g
# bind to queue
q.get = newget(q)

# test
items = range(10)
for it in items:
    q.put(*(it, it))

while not q.empty():
    print q.get()

If this is to be made to a more robust code I strongly recommend using a class and not just re-bind the methods.如果这是为了更健壮的代码,我强烈建议使用类,而不仅仅是重新绑定方法。

You can use a customized Class instead of a tuple.您可以使用自定义类而不是元组。 Then you can do whatever you like in the cmp.然后你可以在 cmp 中做任何你喜欢做的事情。

If you'd like to avoid multiplying by -1 when putting to the priority queue.如果您想在放入优先级队列时避免乘以 -1。 You can do something like this.你可以做这样的事情。

Make a wrapper class制作一个包装类

class Wrapper:
    def __init__(self, value):
        self.value = value
    
    def __lt__(self, next):
        return self.value[0] > next.value[0]

Notice that I've modified the __lt__ function, I've used > instead of < deliberately.请注意,我修改了__lt__函数,我特意使用了>而不是<

Now for putting an element to the Priority Queue do现在将元素放入优先级队列

from queue import PriorityQueue
pq = PriorityQueue()
pq.put(Wrapper((priority, 'extra data')))

Now while getting the element make sure to use the value attribute instead现在在获取元素时确保使用value属性代替

t = pq.get().value

By definition you can only retrieve items from the front of a queue.根据定义,您只能从队列前端检索项目。 To reverse the order, you could push everything onto a stack, and then pop items off the stack.要颠倒顺序,您可以将所有内容推入堆栈,然后从堆栈中弹出项目。 Since a stack both adds and retrieves items from its back, this has the same effect as reversing the queue.由于堆栈从其背面添加和检索项目,因此这与反转队列具有相同的效果。

In the case of Queue.PriorityQueueQueue.PriorityQueue的情况下

The lowest valued entries are retrieved first (the lowest valued entry is the one returned by sorted(list(entries))[0]).首先检索最低值的条目(最低值的条目是 sorted(list(entries))[0] 返回的条目)。

So can you try queue.LifoQueue .It is of LIFO mechanism.所以你可以试试queue.LifoQueue它是LIFO机制。

According to the spec (assuming python 2.7):根据规范(假设 python 2.7):

The lowest valued entries are retrieved first

So that would mean, no, you can't.所以这意味着,不,你不能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM