2010-03-22 2 views
5

Comment puis-je trier facilement et facilement une liste de tuples sans étant sensible à la casse?Trier une liste de tuples sans sensibilité à la casse

Par exemple ceci:

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

devrait ressembler à ceci une fois trié:

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

Le genre régulier lexicographique mettra 'A' avant 'a' et donner ceci:

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

Répondre

10

Vous pouvez utiliser l'argument key pour définir comment vous souhaitez considérer chaque élément par rapport au tri:

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) 

Voir http://wiki.python.org/moin/HowTo/Sorting pour une explication de la façon d'utiliser key.

+0

Cool, j'été essayer de comprendre comment utiliser la clé dans cette situation et l'utilisation de map() ne m'est pas venu à l'esprit. Merci! –

0

Quelque chose comme cela devrait fonctionner:

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] 

En d'autres termes, créer une nouvelle liste, chaque élément est un tuple composé de l'ancien tuple, préfixé avec le même tuple avec chaque élément en minuscules. Puis trier ça.

C'est un peu plus rapide que d'utiliser l'argument de la fonction de comparaison optionnelle de sort, si votre liste est longue.

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

Belle solution compacte. Merci! –

+0

Si vos tuples peuvent contenir d'autres tuples ou structures de séquence, alors vous voudrez probablement la solution lower_if_possible, enveloppée dans un appelant récursif appelé quelque chose comme lower_sequence, qui s'appelle elle-même si elle trouve un membre qui est lui-même une séquence. – PaulMcG

0

Voici une solution qui utilise l'idée de décorateur illustré dans la section d'un article wiki Python « trié par touches » (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

Une version simplifiée de Paul McGuires fonctionne:

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

(où t [0] références quel élément tuple vous souhaitez utiliser, dans ce cas, le premier)

Questions connexes