2009-10-04 8 views
15

Je dois trier une liste python, avec plusieurs attributs. Je peux le faire dans l'ordre croissant pour tous les attributs facilement avecPython: tri par liste avec plusieurs attributs et ordre mélangé

L.sort(key=operator.attrgetter(attribute)).... 

mais le problème est que j'utiliser des configurations mixtes pour monter/descendre ... Je dois « imiter » un peu l'ordre SQL Par où vous pouvez faire quelque chose comme "nom ASC, année DESC". Existe-t-il un moyen de le faire facilement en python sans avoir à implémenter une fonction de comparaison personnalisée?

+3

@ecatmur Cette question est plus ancienne que l'autre. Le doublon est l'inverse. – Jesse

Répondre

26

Si vos attributs sont numériques, vous avez cela. Si vos attributs incluent des chaînes ou d'autres objets plus complexes, vous avez quelques choix. La méthode .sort() est stable: vous pouvez faire plusieurs passes. C'est peut-être le plus simple. C'est aussi remarquablement rapide.

def key1(a): return a.attribute1 
def key2(a): return a.attribute2 

someList.sort(key=key2, reverse=True) 
someList.sort(key=key1) 

S'il s'agit du seul type, vous pouvez définir vos propres opérateurs de comparaison à des fins spéciales. Au minimum, vous avez besoin de __eq__ et __lt__. Les quatre autres peuvent être dérivés de ces deux par simple logique.

+0

merci! callint sort() plusieurs fois s'est avéré être la solution parfaite pour moi! –

+0

Merci pour votre réponse! Juste un peu de confusion concernant la première partie; le retour d'un tuple effectue-t-il un tri complexe avec des valeurs d'index plus élevées prenant moins de priorité? Je suppose que ma question est plus générale, comment se comporte 'cmp' lorsqu'il est remis deux tuples? J'ai regardé autour et ne peux pas trouver ceci documenté. –

+0

__eq__ peut être dérivé de __lt__ en utilisant une logique simple. :) – Tony

5

Vous ne pouvez pas, mais l'écriture de la fonction de comparaison est facile:

def my_cmp(a, b): 
    return cmp(a.foo, b.foo) or cmp(b.bar, a.bar) 
L.sort(my_cmp) 
7

Une fonction personnalisée rendra votre code plus lisible. Si vous avez de nombreuses opérations de tri et vous ne voulez pas créer ces fonctions cependant, vous pouvez utiliser de lambda:

L.sort(lambda x, y: cmp(x.name, y.name) or -cmp(x.year, y.year))