2010-06-25 23 views
381

Tengo algunos datos en la lista contiene listas, o la lista contiene tuplas.¿Cómo ordenar (lista/tupla) de listas/tuplas?

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

Y quiero ordenar por el segundo elemento en el subconjunto. Es decir, ordenando por 2,5,8 donde 2 es de (1,2,3), 5 es de (4,5,6). ¿Cuál es la forma común de hacer esto? ¿Debo almacenar tuplas o listas en mi lista? Dado que las tuplas son más inflexibles.

+24

Con respecto a "? ¿Debo almacenar tuplas o listas en mi lista", una regla de oro es para hacer las cosas tan inmutable como sea posible. Si no * necesita * modificar las sublistas en su lugar, conviértalas en tuplas. –

Respuesta

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

o:

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

¿Alguna idea de cómo ordenarla de mayor a menor? – billwild

+42

@billwild: ayuda (clasificada). reverso = Verdadero. – Stephen

+22

@Stephen usando itemgetter es más rápido y simple: 'key = itemgetter (1)' y al principio del archivo: 'from operator import objectgetter' – Joschua

25

Stephen's answer es el que yo uso. Para completar, aquí está el patrón de ESD (decorar-tipo-Undecorate) con listas por comprensión:

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

O, más concisamente:

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

Como se señaló en el Python Sorting HowTo, esto ha sido innecesaria, ya que Python 2.4 , cuando las funciones clave estuvieron disponibles.

+2

¿Entonces esta respuesta es útil para Python 2.3-? ¿Hay algún uso válido en las versiones de Python más actuales en torno a las cuales podrías elaborar un poco? Si no, no se molestó ... estaba pasando, vio esto y el viejo amigo empezó a revolver un poquito. De todos modos, aplausos y gracias por este paseo en los primeros días de Python. – bernie

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

_Esto debería ser la respuesta aceptada._ Véase también [Charlie] (https://stackoverflow.com/users/145976/charlie) 's [horarios publicados] (https://stackoverflow.com/a/17243726/2809027) , demostrando que la clase 'itemgetter' ordena ** 126% más rápido ** en promedio que la función equivalente 'lambda'. –

+0

x = [[[5,3], 1.0345], [[5,6], 5.098], [[5,4], 4.89], [[5,1], 5.97]] Con una lista como esta es ¿Podemos ordenar utilizando itemgetter() con respecto a los elementos en 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 como esta es , ¿cómo podemos ordenar con respecto a los elementos en x [0] [1]? – nidHi

-6

Ordenar una tupla es bastante simple:

tuple(sorted(t)) 
28

sólo quiero añadir a la respuesta de Stephen si desea ordenar la matriz de mayor a menor, de otra forma que no sea en los comentarios de arriba es acaba de añadir esto a la línea:

reverse = True 

y el resultado será el siguiente:

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

Para la clasificación por varios criterios, a saber, por ejemplo, por los elementos segundo y tercero de una tupla, dejar

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

y así definir un lambda que devuelve una tupla que describe prioridad, por ejemplo

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

Sin lambda:

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

itemgetter() es algo más rápido que lambda tup: tup[1], pero el aumento es relativamente modesto (alrededor de 10 a 25 por ciento).

(sesión 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 
4

Con el fin de ordenar una lista de tuplas (<word>, <count>), por count en orden y word descendente en orden alfabético:

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

que utiliza este método:

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

y me da el resultado:

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

@Stephen ¡la respuesta va al grano! Aquí hay un ejemplo para una mejor visualización,

¡Grite para los fanáticos de 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 es una función que será llamada para transformar los elementos de la colección para la comparación .. como compareTo método en Java.

El parámetro pasado a la clave debe ser algo que se puede llamar. Aquí, el uso de lambda crea una función anónima (que es invocable).
La sintaxis de lambda es la palabra lambda seguida de un nombre iterable y luego de un solo bloque de código.

Por debajo del ejemplo, estamos ordenando una lista de tuplas que contiene la información en tiempo de ciertos eventos y nombres de actores.

Estamos ordenando esta lista por momento de ocurrencia del evento, que es el 0º elemento de una tupla.

Nota - s.sort([cmp[, key[, reverse]]]) ordena los elementos de s en lugar