web-dev-qa-db-fra.com

Comment placer des éléments dans des files d'attente prioritaires?

Dans les documents Python,

Les entrées les moins valorisées sont récupérées en premier (l'entrée la moins valorisée est celle renvoyée par sorted(list(entries))[0]). Un modèle typique pour les entrées est un Tuple sous la forme: (priority_number, data).

Il semble que la file d'attente sera triée par priorité, puis par données, ce qui n'est pas toujours correct. Supposons que les données "élément 2" soient mises en file d'attente avant "élément 1", l'élément 1 ira toujours en premier. Dans une autre page de documentation, heapq , il suggère l'utilisation d'un compteur. Je vais donc stocker mes données comme entry = [priority, count, task]. N'y a-t-il pas quelque chose comme

PriorityQueue.put(item, priority)

Alors je n'aurai pas besoin de mettre en œuvre la commande moi-même?

33
Jiew Meng

Pour autant que je sache, ce que vous recherchez n'est pas disponible dès le départ. Quoi qu'il en soit, notez qu'il ne serait pas difficile à mettre en œuvre:

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()

Exemple de sortie:

item2
item1
29
jcollado

Utilisez simplement le deuxième élément du Tuple comme priorité secondaire si un tri alphanumérique sur vos données de chaîne n'est pas approprié. Une priorité date/heure vous donnerait une file d'attente prioritaire qui revient à une file d'attente FIFIO lorsque vous avez plusieurs éléments avec la même priorité. Voici un exemple de code avec juste une priorité numérique secondaire. L'utilisation d'une valeur datetime en deuxième position est un changement assez trivial, mais n'hésitez pas à me pousser dans les commentaires si vous n'êtes pas en mesure de le faire fonctionner.

Code

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)

Production

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

Éditer

Voici à quoi cela ressemble si vous utilisez un horodatage pour simuler FIFO comme priorité secondaire en utilisant une date. Je dis faux parce que ce n'est qu'environ FIFO comme entrées qui sont ajoutés très proches dans le temps les uns des autres peuvent ne pas sortir exactement FIFO. J'ai ajouté un bref sommeil afin que cet exemple simple fonctionne de manière raisonnable. J'espère que cela vous aidera comme un autre exemple de la façon dont vous pourriez obtenir la commande que vous recherchez.

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

J'ai fait quelque chose comme ça pour accomplir un FIFO similaire à gfortune, mais sans avoir besoin d'appeler time.time () partout: (Python 3 uniquement)

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)

Vous pouvez maintenant faire:

import queue

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

Et assurez-vous qu'ils seront toujours extraits dans le même ordre.

0
Rene