2013-08-24 12 views
8

Se ho una lista di tuple:Come si ordinano le tuple in ordine inverso, eppure si rompono i legami non invertiti? (Python)

results = [('10', 'Mary'), ('9', 'John'), ('10', 'George'), ('9', 'Frank'), ('9', 'Adam')] 

Come posso ordinare l'elenco come si può vedere in un quadro di valutazione - tale che ordinerà il punteggio dal più grande al più piccolo, ma rompere i legami in ordine alfabetico per nome?

Così, dopo l'ordinamento, la lista dovrebbe essere simile:

results = [('10', 'George'), ('10', 'Mary'), ('9', 'Adam'), ('9', 'Frank'), ('9', 'John')] 

Al momento tutto quello che posso fare è results.sort(reverse=True), ma rompe i legami invertire alfabetico troppo ...

Qualsiasi aiuto sarebbe molto apprezzato. Grazie!

+1

''10' <'9' è True' e' 'Adam' <'Frank' è True'. Immagino tu voglia fare "10"> "9"? – Kabie

+0

Perché hai stringhe invece di inte per i tuoi numeri? – user2357112

+0

Questo è un buon punto !! Non ci ho pensato. Tutti i miei numeri sono ora, ma sono ancora incerto su come ordinare il reverse e rompere i legami non-reverse ... – chillman

risposta

14

Il modo più semplice per ottenere ciò che vuoi è usare il fatto che l'ordinamento python è stabile. Questo permette alla prima ordina alfabeticamente e poi il punteggio:

In [11]: results = [(10, 'Mary'), (9, 'John'), (10, 'George'), (9, 'Frank'), (9, 'Adam')] 

In [12]: results.sort(key=lambda x: x[1]) 

In [13]: results.sort(key=lambda x: x[0], reverse=True) 

In [14]: results 
Out[14]: [(10, 'George'), (10, 'Mary'), (9, 'Adam'), (9, 'Frank'), (9, 'John')] 

I primi tipi di ordinamento alfabetico, in ordine ascendente. Il secondo tipo ordina per punteggio, in ordine decrescente, mantenendo l'ordine relativo di elementi con punteggio uguale.

È possibile eseguire questa operazione per eseguire tipi ancora più complessi. Ricorda che devi prima ordinare la chiave secondaria e poi con la prima chiave. (Se hai tre chiavi, prima ordina il terzo, poi il secondo e infine il tasto principale).

Se non si desidera chiamare il numero sort due volte sarà necessario scrivere una funzione più complessa key. Qualcosa di simile:

In [50]: def key(elem): 
    ...:  return elem[0], [-ord(c) for c in elem[1]] 

In [51]: sorted(results, key=key, reverse=True) 
Out[51]: [(10, 'George'), (10, 'Mary'), (9, 'Adam'), (9, 'Frank'), (9, 'John')] 

In particolare, ogni volta che avete qualcosa ordinati in ordine lessicografico (come le stringhe, tuple, liste, ecc), è possibile invertire l'ordine cambiando il segno a tutti gli elementi.

+0

Grazie fantastici! – chillman

+1

Può essere utile notare che è possibile evitare parte della complessità del proprio esempio di "chiamata di un tipo" utilizzando l'ordinamento crescente predefinito e invertendo il numero anziché la stringa 'ordinata (risultati, chiave = lambda x: (-x [ 0], x [1])) ' – Daniel

0

Usando solo sorted dovrebbe essere sufficiente

>>> sorted(results) 
[('10', 'George'), ('10', 'Mary'), ('9', 'Adam'), ('9', 'Frank'), ('9', 'John')] 

predefinita cmp funzione assegni precedenza di una tupla confrontando ciascun membro della tupla, da 0 a n, in questo ordine

+0

Ah, capisco - il problema è che se i numeri sono qualsiasi altra cosa, questo non funzionerà ... cattivo esempio, suppongo :) scusa – chillman

5

sort metodo accettare parametro opzionale key.

chiave specifica una funzione di un argomento che viene usato per estrarre una chiave di confronto da ogni elemento della lista

è necessario convertire stringa in numero di:

>>> results = [('10', 'Mary'), ('9', 'John'), ('10', 'George'), ('9', 'Frank'), ('9', 'Adam')] 
>>> results.sort(key=lambda x: (int(x[0]), x[1]), reverse=True) 
>>> results 
[('10', 'Mary'), ('10', 'George'), ('9', 'John'), ('9', 'Frank'), ('9', 'Adam')] 
0

È possibile avere un controllo molto granulare su come ordinare ciascuno dei valori in una tupla con il parametro key del metodo . Ad esempio:

In [41]: results = [('10', 'Mary'), ('9', 'John'), ('10', 'George'), ('9', 'Frank'), ('9', 'Adam')] 

In [42]: results.sort(key=lambda (score, name): (-int(score), name)) 

In [43]: results 
Out[43]: 
[('10', 'George'), 
('10', 'Mary'), 
('9', 'Adam'), 
('9', 'Frank'), 
('9', 'John')] 
Problemi correlati