Come ordinare un elenco / tupla di elenchi / tuple dall'elemento in un determinato indice?


659

Ho alcuni dati in un elenco di elenchi o in un elenco di tuple, come questo:

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

E voglio ordinare in base al secondo elemento nel sottoinsieme. Il significato, l'ordinamento per 2,5,8 da dove 2viene (1,2,3), 5viene da (4,5,6). Qual è il modo comune per farlo? Devo memorizzare tuple o elenchi nella mia lista?


51
Per quanto riguarda "Devo memorizzare le tuple o gli elenchi nella mia lista?", Una regola empirica è quella di rendere le cose il più immutabili possibile. Se non è necessario modificare le liste secondarie in atto, renderle tuple.
Matthew Flaschen,

Risposte:


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

o:

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

10
Qualche idea su come ordinare da più grande a più piccolo?
Billwild,

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

34
@Stephen utilizzando itemgetter è più veloce e più semplice: key=itemgetter(1)e all'inizio del file:from operator import itemgetter
Joschua,

3
@Cemre come per il secondo esempio, sortecco un metodo di Listoggetto di Python, che riceve una funzione lambda come keyparametro. Puoi chiamarlo come tup, o t, o come ti piace e funzionerà ancora. tupqui specifica l'indice della tupla dell'elenco, quindi 1significa che l'ordinamento verrà eseguito dai secondi valori delle tuple dell'elenco originale ( 2, 5, 8).
Neurotrasmettitore

1
Ero leggermente scettico sull'affermazione infondata secondo cui "l'uso di itemgetter è più veloce e più semplice". Sebbene io consideri soggettivamente l' lambdaapproccio intuitivo come più semplice della itemgetterclasse itemgetter non intuitiva , sembra effettivamente essere più veloce . Sono curioso di sapere perché. Il mio crudo sospetto è che a lambdaincoraggi il costo nascosto di catturare tutte le variabili locali in un contesto di chiusura, mentre itemgetterun'istanza no. tl; dr: usa sempre itemgetter, perché la velocità vince.
Cecil Curry,

236
from operator import itemgetter
data.sort(key=itemgetter(1))

37
Questa dovrebbe essere la risposta accettata. Vedi anche Charlie 's tempi pubblicati , a dimostrazione della itemgetterclasse per ordinare 126% più veloce , in media, che l'equivalente lambdadella funzione.
Cecil Curry,

9
Puoi anche ordinare gerarchicamente per più indici, ad es.data.sort(key=itemgetter(3,1))
Michael Ohlrogge l'

58

Voglio solo aggiungere alla risposta di Stephen se vuoi ordinare l'array da alto a basso, un altro modo diverso da quello nei commenti sopra è solo quello di aggiungere questo alla riga:

reverse = True

e il risultato sarà il seguente:

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

48

Per l'ordinamento in base a più criteri, vale a dire, ad esempio, per il secondo e il terzo elemento in una tupla, let

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

e quindi definire un lambda che restituisca una tupla che descriva la priorità, per esempio

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

28

La risposta di Stephen è quella che userei. Per completezza, ecco il modello DSU (decorate-ordina-undecorate) con la comprensione dell'elenco:

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

O, più tersamente:

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

Come notato nell'ordinamento Python , ciò non è stato necessario da Python 2.4, quando sono diventate disponibili le funzioni chiave.


2
Quindi questa risposta è utile per Python 2.3-? Ci sono usi validi nelle versioni più attuali di Python intorno alle quali potresti elaborare un po '? Altrimenti, nessun problema ... stava solo passando, vide questo e il vecchio noggin cominciò a agitarsi un pochino. Comunque, applausi e grazie per questa camminata nei primi giorni di Python.
Mechanical_meat

19

Per ordinare un elenco di tuple (<word>, <count>), countin ordine decrescente e wordin 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)]

1
cosa succede se tup [1] è una stringa?
Eric

12

Senza lambda:

def sec_elem(s):
    return s[1]

sorted(data, key=sec_elem)

9

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

(Sessione IPython)

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

Si prega di consultare la soluzione di ordinamento itemgetter per vari argomenti inversi per più colonne qui, quindi è necessario disporre l'ordinamento in più passaggi consecutivi: stackoverflow.com/questions/14466068/…
Lorenz

6

La risposta di @Stephen è 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 verrà chiamata per trasformare gli oggetti della collezione per il confronto .. come il compareTometodo in Java.

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

Sotto l'esempio, stiamo ordinando un elenco di tuple che contiene le informazioni al momento giusto di un determinato evento e il nome dell'attore.

Stiamo ordinando questo elenco in base al momento in cui si verifica l'evento - che è il nono elemento di una tupla.

Nota: s.sort([cmp[, key[, reverse]]]) ordina gli elementi di s in atto


-5

Ordinare una tupla è abbastanza semplice:

tuple(sorted(t))
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.