Как поместить элементы в приоритетные очереди? - PullRequest
33 голосов
/ 15 февраля 2012

В документации по Python,

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

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

PriorityQueue.put(item, priority)

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

Ответы [ 3 ]

32 голосов
/ 15 февраля 2012

Просто используйте второй элемент кортежа в качестве вторичного приоритета, если алфавитно-цифровая сортировка ваших строковых данных не подходит. Приоритет даты / времени даст вам очередь с приоритетом, которая возвращается к очереди 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)
29 голосов
/ 15 февраля 2012

Насколько я знаю, то, что вы ищете, не доступно из коробки. В любом случае, обратите внимание, что это не составит труда реализовать:

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
0 голосов
/ 09 апреля 2019

Я сделал что-то подобное для создания 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)

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...