2010-10-20 14 views
8

Ho una lista strano costruita nel modo seguente:pitone: come ordinare un elenco complesso su due chiavi diverse

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

e voglio ordinare in primo luogo per il numero (decrescente) e poi, se il numero è lo stesso, con il nome (asc). Così il risultato mi piacerebbe avere è:

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

ho cercato di pensare a una funzione lambda che posso usare nel metodo di ordinamento, ma non sono sicuro che posso farlo.

+1

possibile duplicato di [Criteri di ordinamento avanzati per un elenco di tuple annidate] (http://stackoverflow.com/questions/3831449/advanced-sorting-criteria-for-a-list-of-nested-tuples) – SilentGhost

risposta

20

Ordina funzioni in pitone permettono di passare una funzione come una sorta chiave:

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

modifiche: 1. ordinamento 2. dimostrare copia e al posto ordinamento

+0

ha bisogno di un ordinamento discendente per il numero – SilentGhost

+0

questo non funziona nel modo che voglio, perché ordina anche il nome in modalità desc (o asc) –

+2

@Giovanni: non è una scatola nera. Vedi come è risolto? e non puoi modificarlo per adattarlo al tuo problema? – SilentGhost

-2

Non è necessario che sia una funzione lambda passata nel metodo sort, in realtà è possibile fornire una funzione reale poiché sono oggetti di prima classe in python.

L.sort(my_comparison_function) 

dovrebbe funzionare bene

+2

- 1 funzione di confronto scompare in Python 3, mentre l'altra risposta è a prova di futuro. –

+0

Ho pensato a questo, ma come posso scrivere una funzione di confronto che funzioni su due chiavi diverse? fondamentalmente ho bisogno di una f ((x [0], x [1]), (y [0], y [1])) –

+0

@Steven: di cosa stai parlando? questa risposta potrebbe essere inutile, ma non per le ragioni per le quali dichiari. [Leggi i documenti] (http://docs.python.org/py3k/library/stdtypes.html#mutable-sequence-types) – SilentGhost

0

        Ecco qualcosa I whipp ed up (per risolvere lo stesso tipo di problema). L'ho controllato solo con le mie ultime versioni di Python installato (OS X). Le parti di importazione sotto ci sono le (clunkily-nome) chiavi di ordinamento: sortKeyWithTwoListOrders e 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

Si può ordinare l'elenco due volte per ottenere il risultato, basta invertire l'ordine:

import operator 

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

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

Quindi si otterrà l'elenco ordinato come previsto.

Problemi correlati