2013-05-13 8 views
16

Come si ordina una lista di stringhe entro il key=len prima, quindi tramite key=str? ho provato quanto segue ma non mi sta dando l'ordinamento desiderato:Come specificare 2 chiavi in ​​python ordinate (lista)?

>>> ls = ['foo','bar','foobar','barbar'] 
>>> 
>>> for i in sorted(ls): 
...  print i 
... 
bar 
barbar 
foo 
foobar 
>>> 
>>> for i in sorted(ls, key=len): 
...  print i 
... 
foo 
bar 
foobar 
barbar 
>>> 
>>> for i in sorted(ls, key=str): 
...  print i 
... 
bar 
barbar 
foo 
foobar 

ho bisogno di ottenere:

bar 
foo 
barbar 
foobar 

risposta

26

definire una funzione chiave che restituisce una tupla in cui il primo elemento è len(str) e il secondo è la stringa stessa. Le tuple vengono poi confrontate lessicograficamente. Cioè, prima vengono confrontate le lunghezze; se sono uguali, le stringhe vengono confrontate.

In [1]: ls = ['foo','bar','foobar','barbar'] 

In [2]: sorted(ls, key=lambda s: (len(s), s)) 
Out[2]: ['bar', 'foo', 'barbar', 'foobar'] 
+0

solo 2c se le prestazioni sono importanti: una funzione autonoma dovrebbe essere molto più veloce di 'lambda'. – bereal

+0

@root: davvero? Perché? – Eric

+2

@Eric - Duh ... Dopo averlo testato, devo dire che non ci sono differenze di prestazioni. – root

2

Se non si desidera utilizzare lambda:

from operator import itemgetter 
ls = ['foo','bar','foobar','barbar'] 
print sorted([ [x,len(x)] for x in ls ] ,key=itemgetter(1,0)) 
# print [s[0] for s in sorted([ [x,len(x)] for x in ls ] ,key=itemgetter(1,0))] 
+3

Questo è più brutto del lambda perché stai introducendo cruft al risultato che richiede un '[0]' in più per accedere al risultato – jamylak

+0

Sì, questo ha il tempo di esecuzione x2 rispetto a lambda – perreal

+0

Inoltre, per me il tempo di esecuzione con key_function è 1.2 volte la versione lambda – perreal

0

Un'altra forma che funziona senza un lambda:

>>> [t[1] for t in sorted((len(s),s) for s in ls)] 
['bar', 'foo', 'barbar', 'foobar'] 
+2

'key' è stata creata in modo da non dover utilizzare DSU – jamylak

12

La risposta da radice è corretto, ma si non ho davvero bisogno di un lambda:

>>> def key_function(x): 
     return len(x), str(x) 

>>> sorted(['foo','bar','foobar','barbar'], key=key_function) 
['bar', 'foo', 'barbar', 'foobar'] 

In addtion, v'è un approccio alternativo si avvale di stabilità genere che consente di ordinare in più passaggi (con la prima chiave secondaria):

>>> ls = ['foo','bar','foobar','barbar'] 
>>> ls.sort(key=str)      # secondary key 
>>> ls.sort(key=len)      # primary key 

Vedere la Sorting HOWTO per un buon tutorial sulle tecniche di ordinamento Python .

+9

Beh, direi che non è necessario eseguire una funzione completa qui :) (A proposito, manca un tasto', key = key_function)) – root

+3

Di fronte a una domanda per principianti, in genere non userò un * lambda * nella risposta e utilizzerò invece la formulazione più semplice della risposta. Se qualcuno sta facendo questa domanda sull'ordinamento e sulle funzioni chiave, allora suggerisce che non sono già a proprio agio con * lambda *. –

+1

Punto preso. Suppongo di aver letto l'uso di * lambda * in questo contesto dovrebbe essere in qualche modo scoraggiato in generale. – root

Problemi correlati