【问题标题】:How do I reverse the order of PriorityQueue in python?如何在 python 中反转 PriorityQueue 的顺序?
【发布时间】:2015-03-25 12:45:25
【问题描述】:

我在 python 中创建了一个简单的优先级队列,它按项目的值排序:

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

但是当我使用以下方式打印队列时:

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

它总是首先打印最低值。有没有办法在不将代码顶部的最后两行更改为:

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

因为如果我想将该信息用于其他用途,这似乎有点混乱并且会产生问题(我必须再次将它乘以 -1)

【问题讨论】:

    标签: python queue priority-queue


    【解决方案1】:

    可以创建您自己的类,该类继承自 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
    

    这似乎至少适用于元组:

    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)
    

    我相信您可以概括代码以处理不仅仅是从这里开始的元组。

    【讨论】:

      【解决方案2】:

      您可以使转换透明。

      您想要的是拥有一个新的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()
      

      如果要编写更健壮的代码,我强烈建议使用类,而不仅仅是重新绑定方法。

      【讨论】:

        【解决方案3】:

        您可以使用自定义类而不是元组。 然后你可以在 cmp 中为所欲为。

        【讨论】:

          【解决方案4】:

          如果您希望在放入优先级队列时避免乘以 -1。你可以这样做。

          制作一个包装类

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

          请注意,我已经修改了__lt__ 函数,我故意使用> 而不是<

          现在将元素放入优先队列中

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

          现在在获取元素时,请确保改用value 属性

          t = pq.get().value
          

          【讨论】:

            【解决方案5】:

            根据定义,您只能从队列的前面检索项目。要颠倒顺序,您可以将所有内容压入堆栈,然后将项目从堆栈中弹出。由于堆栈从其后面添加和检索项目,这与反转队列具有相同的效果。

            【讨论】:

            • 但这意味着每次我想从队列后面取出一些东西时都将所有东西都推到堆栈上,不是吗?我想这将是非常低效的,尤其是对于非常大的输入大小..
            【解决方案6】:

            Queue.PriorityQueue的情况

            首先检索最低值的条目(最低值的条目是由 sorted(list(entries))[0] 返回的条目。

            那么你可以试试queue.LifoQueue。它是LIFO机制。

            【讨论】:

              【解决方案7】:

              根据spec(假设python 2.7):

              The lowest valued entries are retrieved first
              

              所以这意味着,不,你不能。

              【讨论】:

              • 很公平,我阅读了规范,但认为我可能缺少另一种特殊方法或其他东西。没关系,我想我可以乘以-1
              猜你喜欢
              • 1970-01-01
              • 2011-07-24
              • 2013-07-15
              • 2021-03-04
              • 1970-01-01
              • 2016-05-09
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多