Как помещать элементы в очереди приоритетов?
В документах Python
Сначала записываются наизнанку записи (наименьшая ценность - та, что возвращается sorted(list(entries))[0]
). Типичным примером для записей является кортеж в форме: (priority_number, data)
.
Кажется, очередь будет сортироваться по приоритету, а затем данные, что может быть не всегда правильным. Предположим, что данные "элемент 2" помещены в очередь до "пункта 1", элемент 1 по-прежнему будет первым. На другой странице документов heapq предлагается использовать счетчик. Поэтому я сохраню свои данные, например entry = [priority, count, task]
. Разве нет что-то вроде
PriorityQueue.put(item, priority)
Тогда мне не нужно будет выполнять заказ самостоятельно?
Ответы
Ответ 1
Насколько я знаю, то, что вы ищете, не доступно из коробки. Во всяком случае, обратите внимание, что это будет непросто реализовать:
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
Ответ 2
Просто используйте второй элемент кортежа в качестве вторичного приоритета, если алфавитно-цифровая сортировка по строковым данным не подходит. Приоритет даты/времени предоставит вам очередь приоритетов, которая возвращается в очередь FIFIO, когда у вас есть несколько элементов с одинаковым приоритетом. Вот пример кода с только вторичным числовым приоритетом. Использование значения datetime во второй позиции - довольно тривиальное изменение, но не стесняйтесь вызывать меня в комментариях, если вы не можете заставить его работать.
код
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 в качестве вторичного приоритета с использованием даты. Я говорю фальшивку, потому что только приблизительно FIFO, поскольку записи, которые добавляются очень близко друг к другу, могут не совпадать точно с 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)
Ответ 3
Я сделал что-то подобное для создания 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)
И будьте уверены, они всегда будут извлечены в одном и том же порядке.