2010-10-20 6 views
8

j'ai une liste bizarre construit de la manière suivante:python: comment trier une liste complexe sur deux clés différentes

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

et je veux trier d'abord par le nombre (desc) puis, si le nombre est le même, par le nom (asc). Ainsi, le résultat que je voudrais avoir est:

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

J'ai essayé de penser à une fonction lambda que je peux utiliser dans la méthode de tri, mais je ne suis pas sûr que je peux le faire.

+1

duplication possible de [Critères de tri avancés pour une liste de tuples imbriqués] (http://stackoverflow.com/questions/3831449/advanced-sorting-criteria-for-a-list-of-nested-tuples) – SilentGhost

Répondre

20

fonctions de tri en python permettent de passer d'une fonction clé de tri:

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

Edits: 1. Ordre de tri 2. démontrer copie et en place tri

+0

il a besoin tri décroissant pour le numéro – SilentGhost

+0

cela ne fonctionne pas comme je le veux, car il trie aussi le nom en mode desc (ou asc) –

+2

@Giovanni: ce n'est pas une boîte noire. Voyez-vous comment cela est résolu? et vous ne pouvez pas le modifier en fonction de votre problème? – SilentGhost

-2

Il ne doit pas nécessairement s'agir d'une fonction lambda que vous transmettez à la méthode sort, vous pouvez réellement fournir une fonction réelle car ce sont des objets de première classe en python.

L.sort(my_comparison_function) 

devrait fonctionner parfaitement

+2

- 1 La fonction de comparaison disparaît dans Python 3, tandis que l'autre réponse est future. –

+0

J'ai pensé à cela, mais comment puis-je écrire une fonction de comparaison qui fonctionne sur deux clés différentes? fondamentalement, j'ai besoin d'un f ((x [0], x [1]), (y [0], y [1])) –

+0

@Steven: de quoi parlez-vous? cette réponse pourrait être inutile, mais pas pour les raisons que vous dites. [Lire les docs] (http://docs.python.org/py3k/library/stdtypes.html#mutable-sequence-types) – SilentGhost

0

        Voici quelque chose que je whipp ed up (pour résoudre le même type de problème). Je l'ai seulement vérifié avec mes dernières versions de Python installé (OS X). Les parties à l'importation ci-dessous sont les clés de tri (clunkily-nommés): sortKeyWithTwoListOrders et 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

Vous pouvez trier la liste deux fois pour obtenir le résultat, juste inverser la commande:

import operator 

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

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

Ensuite, vous obtiendrez la liste triée comme prévu.

Questions connexes