Подтвердить что ты не робот

Как помещать элементы в очереди приоритетов?

В документах Python

Сначала записываются наизнанку записи (наименьшая ценность - та, что возвращается sorted(list(entries))[0]). Типичным примером для записей является кортеж в форме: (priority_number, data).

Кажется, очередь будет сортироваться по приоритету, а затем данные, что может быть не всегда правильным. Предположим, что данные "элемент 2" помещены в очередь до "пункта 1", элемент 1 по-прежнему будет первым. На другой странице документов heapq предлагается использовать счетчик. Поэтому я сохраню свои данные, например entry = [priority, count, task]. Разве нет что-то вроде

PriorityQueue.put(item, priority)

Тогда мне не нужно будет выполнять заказ самостоятельно?

4b9b3361

Ответ 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)

И будьте уверены, они всегда будут извлечены в одном и том же порядке.