python - una - ¿Cómo ordenar(lista/tupla) de listas/tuplas?
ordenar varias listas python (10)
Tengo algunos datos en una lista de listas o en una lista de tuplas, como esta:
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, clasificando 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 las tuplas o listas en mi lista?
¡La respuesta de @Stephen es al punto! Aquí hay un ejemplo para una mejor visualización,
¡Grita por 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 se llamará para transformar los elementos de la colección para su comparación ... como compareTo
método compareTo
en Java.
El parámetro pasado a clave debe ser algo que sea llamable. Aquí, el uso de lambda
crea una función anónima (que se puede llamar).
La sintaxis de lambda es la palabra lambda seguida de un nombre iterable y luego un solo bloque de código.
A continuación del ejemplo, estamos ordenando una lista de tuplas que contiene la información sobre el tiempo de cierto evento y nombre del actor.
Estamos ordenando esta lista por el momento en que ocurre el evento, que es el elemento 0 de una tupla.
Nota: s.sort([cmp[, key[, reverse]]])
ordena los elementos de s en su lugar
La clasificación de una tupla es bastante simple:
tuple(sorted(t))
Para clasificar por múltiples criterios, a saber, por ejemplo, por el segundo y tercer elementos en una tupla, deje
data = [(1,2,3),(1,2,1),(1,1,4)]
y así definir un lambda que devuelve una tupla que describe la prioridad, por ejemplo
sorted(data, key=lambda tup: (tup[1],tup[2]) )
[(1, 1, 4), (1, 2, 1), (1, 2, 3)]
Para ordenar una lista de tuplas (<word>, <count>)
, para count
en orden descendente y word
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)]
Yo uso 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)]
Sin lambda:
def sec_elem(s): return s[1]
sorted(data, key=sec_elem)
Solo quiero agregar a la respuesta de Stephen si desea ordenar la matriz de alta a baja, otra forma que no sea en los comentarios anteriores es simplemente agregar esto a la línea:
reverse = True
y el resultado será el siguiente:
data.sort(key=lambda tup: tup[1], reverse=True)
La respuesta de Stephen es la que yo usaría. Para completar, aquí está el patrón DSU (decorate-sort-undecorate) con listas de comprensión:
decorated = [(tup[1], tup) for tup in data]
decorated.sort()
undecorated = [tup for second, tup in decorated]
O, más tersamente:
[b for a,b in sorted((tup[1], tup) for tup in data)]
Como se señaló en el Cómo ordenar de Python , esto no ha sido necesario desde Python 2.4, cuando las funciones clave estuvieron disponibles.
itemgetter()
es algo más rápido que lambda tup: tup[1]
, pero el aumento es relativamente modesto (alrededor del 10 al 25 por ciento).
(Sesión de 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
from operator import itemgetter
data.sort(key=itemgetter(1))
sorted_by_second = sorted(data, key=lambda tup: tup[1])
o:
data.sort(key=lambda tup: tup[1]) # sorts in place