2010-07-09 12 views
37

Come si ordina una lista per una chiave descritta da una funzione arbitraria? Ad esempio, se ho:Ordinamento per lambda arbitrario

mylist = [["quux", 1, "a"], ["bar", 0, "b"]] 

desidero ordinare "mylist" dal secondo elemento di ciascun elemento, ad esempio

sort(mylist, key=lambda x: x[1]) 

come posso fare questo?

+0

Qual è stato il problema quando hai provato il codice che fornisci? – tzot

risposta

37

Hai sostanzialmente già:

>>> mylist = [["quux", 1, "a"], ["bar", 0, "b"]] 
>>> mylist.sort(key=lambda x: x[1]) 
>>> print mylist 

dà:

[['bar', 0, 'b'], ['quux', 1, 'a']] 

Questo ordinerà la mia lista in posizione.

[questa para modificato grazie a @ correzione di Daniel.] sorted restituirà un nuovo elenco che viene ordinata piuttosto che effettivamente cambiare l'ingresso, come descritto in http://wiki.python.org/moin/HowTo/Sorting/.

+0

Buono a sapersi distinguere, grazie. – user248237dfsf

4

La risposta è quella di utilizzare "ordinato", vale a dire

sorted(mylist, key=lambda x: x[1]) 
+0

Ho avuto i parametri all'indietro. Sembra incoerente che ad es. map/filter/reduce prende il primo parametro lambda ed elenca il secondo parametro, ma ordina il contrario. – javadba

7

Hai due opzioni, molto vicino a quello che hai descritto, in realtà:

mylist.sort(key=lambda x: x[1]) # In place sort 
new_list = sorted(mylist, key=lambda x: x[1]) 
9

Questa è una necessità comune che il supporto per esso è stato aggiunto alla libreria standard, sotto forma di operator.itemgetter:

from operator import itemgetter 
mylist = [["quux", 1, "a"], ["bar", 0, "b"]] 
mylist.sort(key=itemgetter(1)) # or sorted(mylist, key=...) 
4

Ordina e itemgetter è il più veloce.

>>> import operator 
>>> import timeit 

>>> mylist = [["quux", 1, "a"], ["bar", 0, "b"]] 
>>> t1 = timeit.Timer(lambda: mylist.sort(key=lambda x: x[1])) 
>>> t1.timeit() 
1.6330803055632404 

>>> t2 = timeit.Timer(lambda: mylist.sort(key=operator.itemgetter(1))) 
>>> t2.timeit() 
1.3985503043467773 

>>> t3 = timeit.Timer(lambda: sorted(mylist, key=operator.itemgetter(1))) 
>>> t3.timeit() 
2.6329514733833292 

>>> t4 = timeit.Timer(lambda: sorted(mylist, key=lambda x: x[1])) 
>>> t4.timeit() 
2.9197154810598533