2010-03-22 3 views
5

Come è possibile ordinare in modo efficiente e semplice un elenco di tuple senza sensibile al caso?Ordinare un elenco di tuple senza distinzione tra maiuscole e minuscole

Per esempio, questo:

[('a', 'c'), ('A', 'b'), ('a', 'a'), ('a', 5)] 

dovrebbe essere simile a questo, una volta ordinato:

[('a', 5), ('a', 'a'), ('A', 'b'), ('a', 'c')] 

L'ordinamento lessicografico regolare metterà 'A' prima 'a' e cedere questo:

[('A', 'b'), ('a', 5), ('a', 'a'), ('a', 'c')] 

risposta

10

È possibile utilizzare l'argomento key per definire come si desidera considerare ogni elemento per quanto riguarda l'ordinamento:

def lower_if_possible(x): 
    try: 
     return x.lower() 
    except AttributeError: 
     return x 

L=[('a', 'c'), ('A', 'b'), ('a', 'a'), ('a', 5)] 

L.sort(key=lambda x: map(lower_if_possible,x)) 
print(L) 

Vedi http://wiki.python.org/moin/HowTo/Sorting per una spiegazione di come utilizzare key.

+0

freddo, mi è stato cercare di capire come usare la chiave in questa situazione e usare map() non mi è venuto in mente. Grazie! –

0

Qualcosa del genere dovrebbe funzionare:

def sort_ci(items): 
    def sort_tuple(tuple): 
     return ([lower(x) for x in tuple],) + tuple 
    temp = [sort_tuple(tuple) for tuple in items] 
    temp.sort() 
    return [tuple[1:] for tuple in temp] 

In altre parole, creare un nuovo elenco, in cui ogni elemento è una tupla consistente della vecchia tupla, preceduto con la stessa tupla con ogni elemento in minuscolo. Quindi ordina questo.

Questo è un po 'più veloce dell'utilizzo dell'argomento della funzione di confronto opzionale sort, se l'elenco è lungo.

2
list_of_tuples.sort(key=lambda t : tuple(s.lower() if isinstance(s,basestring) else s for s in t)) 
+0

Soluzione semplice e compatta. Grazie! –

+0

Se le tue tuple possono contenere altre tuple o strutture di sequenza, probabilmente vorrai la soluzione lower_if_possible, racchiusa all'interno di un chiamante ricorsivo chiamato qualcosa come lower_sequence, che si chiama se trova un membro che è esso stesso una sequenza. – PaulMcG

0

Ecco una soluzione che utilizza l'idea decoratore illustrata nella sezione "ordinati per chiavi" di un articolo Python wiki (http://wiki.python.org/moin/HowTo/Sorting/).

# Create a list of new tuples whose first element is lowercase 
# version of the original tuple. I use an extra function to 
# handle tuples which contain non-strings. 
f = lambda x : x.lower() if type(x)==str else x 
deco = [(tuple(f(e) for e in t), t) for t in ex] 

# now we can directly sort deco and get the result we want 
deco.sort() 

# extract the original tuples in the case-insensitive sorted order 
out = [t for _,t in deco] 
0

Una versione semplificata di Paolo McGuires funziona:

list_of_tuples.sort(key=lambda t : tuple(t[0].lower())) 

(dove t [0] riferimenti quale elemento tuple che si desidera utilizzare, in questo caso il primo)