2009-10-04 14 views
15

Tengo que ordenar una lista de python, con múltiples atributos. Puedo hacer eso en orden ascendente para todos los atributos fácilmente conPython: ordenación de lista con múltiples atributos y orden mixto

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

pero el problema es que tengo que usar configuraciones mixtas para ascendente/descendente ... tengo que "imitan" un poco la Orden de SQL Por donde puede hacer algo como "nombre ASC, año DESC". ¿Hay alguna manera de hacer esto fácilmente en python sin tener que implementar una función de comparación personalizada?

+3

@ecatmur Esta pregunta es anterior a la otra. El duplicado es al revés. – Jesse

Respuesta

26

Si sus atributos son numéricos, sufre esta enfermedad.

def mixed_order(a): 
    return (a.attribute1, -a.attribute2) 

someList.sort(key=mixed_order) 

Si sus atributos incluyen cadenas u otros objetos más complejos, tiene algunas opciones.

El método .sort() es estable: puede hacer varias pasadas. Este es quizás el más simple. También es notablemente rápido.

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

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

Si este es el único tipo, puede definir sus propios operadores de comparación de propósito especial. Como mínimo, necesita __eq__ y __lt__. Los otros cuatro pueden derivarse de estos dos por simple lógica.

+0

gracias! callint sort() varias veces resultó ser la solución perfecta para mí! –

+0

Gracias por su respuesta! Solo un poco de confusión con respecto a la primera parte; ¿devuelve una tupla una clasificación compleja con valores de índice más altos que tienen una precedencia más baja? Supongo que mi pregunta es más general, ¿cómo se comporta 'cmp' cuando se le entregan dos tuplas? Miré a mi alrededor y no puedo encontrar esto documentado. –

+0

__eq__ se puede derivar de __lt__ usando lógica simple. :) – Tony

5

No se puede, pero escribir la función de comparación es fácil:

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

Una función personalizada hará que el código sea más legible. Si tiene muchas operaciones de clasificación y no desea crear esas funciones, sin embargo, se puede utilizar lambda de:

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