2010-06-25 3 views
381

Ho alcuni dati o in lista contiene elenchi, o lista contiene tuple.Come ordinare (lista/tupla) di liste/tuple?

data = [[1,2,3], [4,5,6], [7,8,9]] 
data = [(1,2,3), (4,5,6), (7,8,9)] 

E voglio ordinare per il 2 ° elemento nel sottoinsieme. Significa, ordinando per 2,5,8 dove 2 è da (1,2,3), 5 è da (4,5,6). Qual è il modo comune per farlo? Devo memorizzare tuple o liste nella mia lista? Poiché le tuple sono più inflessibili.

+24

per quanto riguarda "? Devo conservare tuple o elenchi nella mia lista", una regola empirica è quello di rendere le cose immutabile come possibile. Se * non * è necessario * per modificare le sottoliste, renderle tuple. –

risposta

706
sorted_by_second = sorted(data, key=lambda tup: tup[1]) 

o:

data.sort(key=lambda tup: tup[1]) # sorts in place 
+6

Qualche idea su come ordinarlo più grande a più piccolo? – billwild

+42

@billwild: help (ordinato). invertire = True. – Stephen

+22

@Stephen usando itemgetter è più veloce e più semplice: 'key = itemgetter (1)' e all'inizio del file: 'dall'operatore import itemgetter' – Joschua

25

Stephen's answer è quello userei. Per completezza, ecco il modello DSU (decorare-sort-undecorate) con list comprehension:

decorated = [(tup[1], tup) for tup in data] 
decorated.sort() 
undecorated = [tup for second, tup in decorated] 

O, più conciso:

[b for a,b in sorted((tup[1], tup) for tup in data)] 

Come notato nel Python Sorting HowTo, questo è stato inutile dal momento che Python 2.4 , quando le funzioni chiave sono diventate disponibili.

+2

Quindi questa risposta è utile per Python 2.3-? Ci sono degli usi validi nelle versioni Python più attuali su cui potresti elaborare un po '? Se no, nessun fastidio ... stava passando, visto questo e il vecchio noggin si mise a sfornare un pochino. Comunque, grazie e grazie per questa passeggiata nei giorni precedenti di Python. – bernie

117
from operator import itemgetter 
data.sort(key=itemgetter(1)) 
+8

_Questa dovrebbe essere la risposta accettata._ Vedi anche [Charlie] (https://stackoverflow.com/users/145976/charlie) "[orari pubblicati] (https://stackoverflow.com/a/17243726/2809027) , dimostrando la classe 'itemgetter' per ordinare ** il 126% più veloce ** in media rispetto alla funzione equivalente' lambda'. –

+0

x = [[[5,3], 1,0345], [[5,6], 5,098], [[5,4], 4,89], [[5,1], 5,97]] Con una lista come questa è possiamo ordinare usando itemgetter() rispetto agli elementi in x [0] [1]? – nidHi

+0

x = [[[5,3], 1,0345], [[5,6], 5,098], [[5,4], 4,89], [[5,1], 5,97]] Con una lista come questa è , come possiamo ordinare rispetto agli elementi di x [0] [1]? – nidHi

-6

Ordinamento di una tupla è abbastanza semplice:

tuple(sorted(t)) 
28

Voglio solo aggiungere alla risposta di Stephen se si desidera ordinare l'array da alto a basso, un altro modo diverso nei commenti di cui sopra è solo per aggiungere questo alla linea:

reverse = True 

e il risultato sarà il seguente:

data.sort(key=lambda tup: tup[1], reverse=True) 
20

Per l'ordinamento per criteri multipli, cioè ad esempio il secondo e il terzo elemento di una tupla, lasciate

data = [(1,2,3),(1,2,1),(1,1,4)] 

e quindi definire una lambda che restituisce una tupla che descrive priorità, ad esempio

sorted(data, key=lambda tup: (tup[1],tup[2])) 
[(1, 1, 4), (1, 2, 1), (1, 2, 3)] 
5

Senza lambda:

def sec_elem(s): 
    return s[1]
sorted(data, key=sec_elem)
2

itemgetter() è leggermente più veloce di lambda tup: tup[1], ma l'aumento è relativamente modesto (circa dal 10 al 25 percento).

(IPython sessione)

>>> from operator import itemgetter 
>>> from numpy.random import randint 
>>> values = randint(0, 9, 30000).reshape((10000,3)) 
>>> tpls = [tuple(values[i,:]) for i in range(len(values))] 

>>> tpls[:5] # display sample from list 
[(1, 0, 0), 
(8, 5, 5), 
(5, 4, 0), 
(5, 7, 7), 
(4, 2, 1)] 

>>> sorted(tpls[:5], key=itemgetter(1)) # example sort 
[(1, 0, 0), 
(4, 2, 1), 
(5, 4, 0), 
(8, 5, 5), 
(5, 7, 7)] 

>>> %timeit sorted(tpls, key=itemgetter(1)) 
100 loops, best of 3: 4.89 ms per loop 

>>> %timeit sorted(tpls, key=lambda tup: tup[1]) 
100 loops, best of 3: 6.39 ms per loop 

>>> %timeit sorted(tpls, key=(itemgetter(1,0))) 
100 loops, best of 3: 16.1 ms per loop 

>>> %timeit sorted(tpls, key=lambda tup: (tup[1], tup[0])) 
100 loops, best of 3: 17.1 ms per loop 
4

Per ordinare un elenco di tuple (<word>, <count>), per count in ordine e word decrescente in ordine alfabetico:

data = [ 
('betty', 1), 
('bought', 1), 
('a', 1), 
('bit', 1), 
('of', 1), 
('butter', 2), 
('but', 1), 
('the', 1), 
('was', 1), 
('bitter', 1)] 

Io uso questo metodo:

sorted(data, key=lambda tup:(-tup[1], tup[0])) 

e mi dà il risultato:

[('butter', 2), 
('a', 1), 
('betty', 1), 
('bit', 1), 
('bitter', 1), 
('bought', 1), 
('but', 1), 
('of', 1), 
('the', 1), 
('was', 1)] 
2

@ La risposta di Stefano è al punto! Ecco un esempio per una migliore visualizzazione,

Grida per i fan di Ready Player One! =)

>>> gunters = [('2044-04-05', 'parzival'), ('2044-04-07', 'aech'), ('2044-04-06', 'art3mis')] 
>>> gunters.sort(key=lambda tup: tup[0]) 
>>> print gunters 
[('2044-04-05', 'parzival'), ('2044-04-06', 'art3mis'), ('2044-04-07', 'aech')] 

key è una funzione che sarà chiamata a trasformare gli elementi della collezione per il confronto .. come compareTo metodo in Java.

Il parametro passato alla chiave deve essere qualcosa che può essere richiamato. Qui, l'uso di lambda crea una funzione anonima (che è un chiamabile).
La sintassi di lambda è la parola lambda seguita da un nome iterabile seguito da un singolo blocco di codice.

Nell'esempio seguente, stiamo ordinando un elenco di tuple che contiene il tempo di inserimento informazioni di determinati eventi e il nome dell'attore.

Stiamo ordinando questo elenco per ora dell'occorrenza dell'evento, che è lo 0 ° elemento di una tupla.

Nota - s.sort([cmp[, key[, reverse]]]) ordina le voci di s localmente