web-dev-qa-db-ja.com

アイテムを優先キューに入れる方法は?

Python docs、

最も低い値のエントリが最初に取得されます(最も低い値のエントリは、sorted(list(entries))[0]によって返されたエントリです)。エントリの一般的なパターンは、(priority_number, data)という形式のタプルです。

キューは優先度、データの順にソートされるように見えますが、データは常に正しいとは限りません。データ「アイテム2」が「アイテム1」の前にキューに入れられ、アイテム1がまだ先にあるとします。別のドキュメントページ heapq では、カウンターの使用が提案されています。したがって、entry = [priority, count, task]のようにデータを保存します。のようなものはありませんか

PriorityQueue.put(item, priority)

次に、自分で順序付けを実装する必要はありませんか?

33
Jiew Meng

私が知る限り、あなたが探しているものはすぐに利用できるわけではありません。とにかく、実装するのは難しくないことに注意してください:

from Queue import PriorityQueue

class MyPriorityQueue(PriorityQueue):
    def __init__(self):
        PriorityQueue.__init__(self)
        self.counter = 0

    def put(self, item, priority):
        PriorityQueue.put(self, (priority, self.counter, item))
        self.counter += 1

    def get(self, *args, **kwargs):
        _, _, item = PriorityQueue.get(self, *args, **kwargs)
        return item


queue = MyPriorityQueue()
queue.put('item2', 1)
queue.put('item1', 1)

print queue.get()
print queue.get()

出力例:

item2
item1
29
jcollado

文字列データの英数字による並べ替えが適切でない場合は、Tupleの2番目の項目を2番目の優先度として使用します。日付/時刻の優先度は、同じ優先度のアイテムが複数ある場合にFIFIOキューにフォールバックする優先度キューを提供します。セカンダリの数値優先度のみを使用したコード例を次に示します。 2番目の位置に日時値を使用することは非常に簡単な変更ですが、機能しない場合は気軽にコメントを投稿してください。

コード

import Queue as queue

prio_queue = queue.PriorityQueue()
prio_queue.put((2, 8, 'super blah'))
prio_queue.put((1, 4, 'Some thing'))
prio_queue.put((1, 3, 'This thing would come after Some Thing if we sorted by this text entry'))
prio_queue.put((5, 1, 'blah'))

while not prio_queue.empty():
    item = prio_queue.get()
    print('%s.%s - %s' % item)

出力

1.3 - This thing would come after Some Thing if we didn't add a secondary priority
1.4 - Some thing
2.8 - super blah
5.1 - blah

編集

タイムスタンプを使用して、FIFOを日付を使用して2番目の優先度として偽造する場合、次のようになります。おおよそFIFOエントリとして短いスリープ時間を追加して、この単純な例が妥当な方法で機能するようにしています。これは、後の順序を取得する方法の別の例として役立つことを願っています。

import Queue as queue
import time

prio_queue = queue.PriorityQueue()
prio_queue.put((2, time.time(), 'super blah'))
time.sleep(0.1)
prio_queue.put((1, time.time(), 'This thing would come after Some Thing if we sorted by this text entry'))
time.sleep(0.1)
prio_queue.put((1, time.time(), 'Some thing'))
time.sleep(0.1)
prio_queue.put((5, time.time(), 'blah'))

while not prio_queue.empty():
    item = prio_queue.get()
    print('%s.%s - %s' % item)
32
gfortune

FIFO gfortuneに似ていますが、どこでもtime.time()を呼び出す必要なしに)を達成するためにこのようなものを作りました:(Python 3のみ)

import time
from dataclasses import dataclass, field

@dataclass(order=True)
class PrioritizedItem:
    prio: int
    timestamp: float = field(init=False, default_factory=time.time)
    data: object = field(compare=False)

できるようになりました:

import queue

item1 = PrioritizedItem(0, "hello world")
item2 = PrioritizedItem(0, "what ever")
q = queue.PriorityQueue()
q.put(item1)
q.put(item2)

そして、必ず同じ順序で抽出されます。

0
Rene