Je souhaite tenir un tas d'objets, pas seulement des nombres. Ils auront un attribut entier que le tas peut trier. La manière la plus simple d'utiliser heaps dans python est heapq, mais comment lui ordonner de trier par un attribut spécifique lors de l'utilisation de heapq?Comment faire pour heapq évaluer le tas hors d'un attribut spécifique?
Répondre
heapq
sortes objets de la même manière list.sort
ne, définir si juste une méthode __cmp__()
au sein de votre définition de classe, qui se compare à une autre instance de la même classe:
def __cmp__(self, other):
return cmp(self.intAttribute, other.intAttribute)
Works en Python 2.x.
En utilisation 3.x:
def __lt__(self, other):
return self.intAttribute < other.intAttribute
Malheureusement, vous ne pouvez pas, bien que ce soit une fonctionnalité souvent demandée.
Une option consisterait à insérer des tuples (clé, valeur) dans le tas. Cependant, cela ne fonctionnera pas si les valeurs lancent une exception lorsqu'elles sont comparées (elles seront comparées en cas d'égalité entre les clés).
Une deuxième option consisterait à définir une méthode __lt__
(inférieure à) dans la classe qui utilisera l'attribut approprié pour comparer les éléments à trier. Cependant, cela peut ne pas être possible si les objets ont été créés par un autre paquet ou si vous avez besoin de les comparer différemment ailleurs dans le programme.
Une troisième option consisterait à utiliser la classe sortedlist du module blist (avertissement: je suis l'auteur). Le constructeur pour sortedlist
prend un paramètre key
qui vous permet de spécifier une fonction pour renvoyer la clé de tri d'un élément, similaire au paramètre key
de list.sort
et sorted
.
J'ai supprimé mon commentaire précédent puisque mon problème avec 'blist' était probablement un PEBCAK (encore merci pour votre module), donc je ne fais que dupliquer la première partie du commentaire précédent: Il est toujours possible de définir une classe avec un' __lt__ 'soit par sous-classe ou par encapsulation. – tzot
Selon l'exemple de la documentation, vous pouvez utiliser tuples, et il trier par le premier élément du tuple:
>>> h = []
>>> heappush(h, (5, 'write code'))
>>> heappush(h, (7, 'release product'))
>>> heappush(h, (1, 'write spec'))
>>> heappush(h, (3, 'create tests'))
>>> heappop(h)
(1, 'write spec')
Alors Si vous ne voulez pas (ou ne pouvez pas?) faire une méthode __cmp__
, vous pouvez extraire manuellement votre clé de tri au moment du push.
Notez que si les premiers éléments d'une paire de tuples sont égaux, d'autres éléments seront comparés. Si ce n'est pas ce que vous voulez, vous devez vous assurer que chaque premier élément est unique.
'__cmp__' est parti dans 3.x. Utilisez '__lt__' à la place. –
'__lt__' fonctionne aussi en Python 2, donc il vaut mieux éviter complètement' __cmp__'. –
Tout comme vous pouvez trier n'importe quel tri en fonction d'un critère autre que le tri naturel de l'objet (par exemple, 'cmp' et' key' pour 'sort'), vous devriez pouvoir dire à' heapq' de trier en fonction d'un clé différente. En d'autres termes, vous ne devriez pas avoir à * redéfinir l'objet lui-même * pour modifier une structure de données particulière qui le contient; vous devriez être capable de simplement dire la structure de données elle-même. C'est une pièce fondamentale notable manquante dans l'API 'heapq'. –