2010-10-20 10 views
8

Tengo una lista raro construido de la siguiente manera:pitón: cómo ordenar una lista compleja en dos claves diferentes

[[name_d, 5], [name_e, 10], [name_a, 5]] 

y quiero a solucionar el problema en primer lugar por el número (desc) y luego, si el número es el mismo, por el nombre (asc). Así, el resultado me gustaría tener es:

[[name_e, 10], [name_a, 5], [name_d, 5]] 

Traté de pensar en una función lambda que puedo usar en el método para ordenar, pero no estoy seguro de que puedo hacerlo.

+1

posible duplicado de [Criterios de clasificación avanzada para una lista de tuplas anidadas] (http://stackoverflow.com/questions/3831449/advanced-sorting-criteria-for-a-list-of-nested-tuples) – SilentGhost

Respuesta

20

Ordenar funciones en Python que permiten pasar una función como una especie clave:

l = [[name_d, 5], [name_e, 10], [name_a, 5]] 
# copy 
l_sorted = sorted(l, key=lambda x: (x[1] * -1, x[0])) 
# in place 
l.sort(key=lambda x: (x[1] * -1, x[0]) 

ediciones: 1. Tipo de ordenación 2. Demostrar copia y en su lugar clasificación

+0

necesita una ordenación descendente para el número – SilentGhost

+0

esto no funciona de la manera que yo quiero, porque ordena también el nombre en modo desc (o asc) –

+2

@Giovanni: no es una caja negra. ¿Ves cómo se resuelve? y no puedes modificarlo para adaptarlo a tu problema? – SilentGhost

-2

No necesita ser una función lambda que pase al método sort, realmente puede proporcionar una función real ya que son objetos de primera clase en python.

L.sort(my_comparison_function) 

debería funcionar bien

+2

- 1 La función de comparación desaparece en Python 3, mientras que la otra respuesta es a prueba de futuro. –

+0

Pensé en esto, pero ¿cómo puedo escribir una función de comparación que funcione con dos teclas diferentes? básicamente necesito una f ((x [0], x [1]), (y [0], y [1])) –

+0

@Steven: ¿de qué estás hablando? esta respuesta puede ser inútil, pero no por las razones que usted indica. [Leer los documentos] (http://docs.python.org/py3k/library/stdtypes.html#mutable-sequence-types) – SilentGhost

0

        Aquí hay algo que yo whipp ed up (para resolver el mismo tipo de problema). Solo lo he comprobado con mis últimas versiones de Python instalado (OS X). Las partes de importación siguientes son las claves de clasificación (-clunkily con nombre): sortKeyWithTwoListOrders y sortKeyWith2ndThen1stListValue


#Tested under Python 2.7.1 & Python 3.2.3: 

import random # Just to shuffle for demo purposes 

# Our two lists to sort 
firstCol=['abc','ghi','jkl','mno','bcd','hjk'] 
secondCol=[5,4,2,1] 

# Build 2 dimensional list [[firstCol,secondCol]...] 
myList = [] 
for firstInd in range(0, len(firstCol)): 
    for secondInd in range(0, len(secondCol)): 
    myList = myList + [[firstCol[firstInd],secondCol[secondInd]]] 

random.shuffle(myList) 

print ("myList (shuffled):") 
for i in range(0,len(myList)): 
    print (myList[i]) 

def sortKeyWithTwoListOrders(item): 
    return secondCol.index(item[1]), firstCol.index(item[0]) 

myList.sort(key=sortKeyWithTwoListOrders) 
print ("myList (sorted according to strict list order, second column then first column):") 
for i in range(0,len(myList)): 
    print (myList[i]) 

random.shuffle(myList) 

print ("myList (shuffled again):") 
for i in range(0,len(myList)): 
    print (myList[i]) 

def sortKeyWith2ndThen1stListValue(item): 
    return item[1], item[0] 

myList.sort(key=sortKeyWith2ndThen1stListValue) 
print ("myList (sorted according to *values*, second column then first column):") 
for i in range(0,len(myList)): 
    print (myList[i]) 

myList (shuffled): 
['ghi', 5] 
['abc', 2] 
['abc', 1] 
['abc', 4] 
['hjk', 5] 
['bcd', 4] 
['jkl', 5] 
['jkl', 2] 
['bcd', 1] 
['ghi', 1] 
['mno', 5] 
['ghi', 2] 
['hjk', 2] 
['jkl', 4] 
['mno', 4] 
['bcd', 2] 
['bcd', 5] 
['ghi', 4] 
['hjk', 4] 
['mno', 2] 
['abc', 5] 
['mno', 1] 
['hjk', 1] 
['jkl', 1] 
myList (sorted according to strict list order, second column then first column): 
['abc', 5] 
['ghi', 5] 
['jkl', 5] 
['mno', 5] 
['bcd', 5] 
['hjk', 5] 
['abc', 4] 
['ghi', 4] 
['jkl', 4] 
['mno', 4] 
['bcd', 4] 
['hjk', 4] 
['abc', 2] 
['ghi', 2] 
['jkl', 2] 
['mno', 2] 
['bcd', 2] 
['hjk', 2] 
['abc', 1] 
['ghi', 1] 
['jkl', 1] 
['mno', 1] 
['bcd', 1] 
['hjk', 1] 
myList (shuffled again): 
['hjk', 4] 
['ghi', 1] 
['abc', 5] 
['bcd', 5] 
['ghi', 4] 
['mno', 1] 
['jkl', 1] 
['abc', 1] 
['hjk', 1] 
['jkl', 2] 
['hjk', 5] 
['mno', 2] 
['jkl', 4] 
['ghi', 5] 
['bcd', 1] 
['bcd', 2] 
['jkl', 5] 
['abc', 2] 
['hjk', 2] 
['abc', 4] 
['mno', 4] 
['mno', 5] 
['bcd', 4] 
['ghi', 2] 
myList (sorted according to *values*, second column then first column): 
['abc', 1] 
['bcd', 1] 
['ghi', 1] 
['hjk', 1] 
['jkl', 1] 
['mno', 1] 
['abc', 2] 
['bcd', 2] 
['ghi', 2] 
['hjk', 2] 
['jkl', 2] 
['mno', 2] 
['abc', 4] 
['bcd', 4] 
['ghi', 4] 
['hjk', 4] 
['jkl', 4] 
['mno', 4] 
['abc', 5] 
['bcd', 5] 
['ghi', 5] 
['hjk', 5] 
['jkl', 5] 
['mno', 5] 
0

Puede ordenar la lista dos veces para obtener el resultado, simplemente revertir la orden:

import operator 

l = [[name_d, 5], [name_e, 10], [name_a, 5]] 

l.sort(operator.itemgetter(1)) 
l.sort(operator.itemgetter(0), reverse=True) 

Luego obtendrá la lista ordenada como se esperaba.

Cuestiones relacionadas