tuplas - como ordenar una lista de numeros en python sin sort
Ordene una lista de tuplas por segundo valor, reverse=True y luego por clave, reverse=False (3)
Necesito ordenar un diccionario por primero, valores con reverse=True
, y para valores repetidos, ordenar por teclas, reverse=False
Hasta ahora tengo esto
dict = [(''B'', 3), (''A'', 2), (''A'', 1), (''I'', 1), (''J'', 1)]
sorted(dict.items(), key=lambda x: (x[1],x[1]), reverse=True)
que vuelve ...
[(''B'', 3), (''A'', 2), (''J'', 1), (''I'', 1), (''A'', 1)]
pero necesito que sea:
[(''B'', 3), (''A'', 2), (''A'', 1), (''I'', 1), (''J'', 1)]
Como puede ver, cuando los valores son iguales, solo puedo ordenar la clave de forma decreciente según lo especificado ... Pero, ¿cómo puedo hacer que se ordenen de manera creciente?
Lo siguiente funciona con su entrada:
d = [(''B'', 3), (''A'', 2), (''A'', 1), (''I'', 1), (''J'', 1)]
sorted(d,key=lambda x:(-x[1],x[0]))
Ya que sus "valores" son numéricos, puede revertir fácilmente el orden al cambiar el signo.
En otras palabras, esta ordenación pone las cosas en orden por valor ( -x[1]
) (el signo negativo coloca primero los números grandes) y luego, para los números que son iguales, ordena de acuerdo con la clave ( x[0]
).
Si sus valores no se pueden "negar" tan fácilmente para colocar primero los elementos grandes, una solución fácil es ordenar dos veces:
from operator import itemgetter
d.sort(key=itemgetter(0))
d.sort(key=itemgetter(1),reverse=True)
que funciona porque la clasificación de python es estable.
Puedes usar collections.defaultdict
:
In [48]: from collections import defaultdict
In [49]: dic=[(''B'', 3), (''A'', 2), (''A'', 1), (''I'', 1), (''J'', 1)]
In [50]: d=defaultdict(list)
In [51]: for x,y in dic:
d[y].append(x)
d[y].sort() #sort the list
ahora d
es algo como:
defaultdict(<type ''list''>, {1: [''A'', ''I'', ''J''], 2: [''A''], 3: [''B'']}
es decir, un nuevo dict
con 1,2,3...
como teclas y los alfabetos correspondientes almacenados en listas como valores.
Ahora puede iterar sobre el sorted(d.items)
y obtener el resultado deseado utilizando itertools.chain()
e itertools.product()
.
In [65]: l=[ product(y,[x]) for x,y in sorted(d.items(),reverse=True)]
In [66]: list(chain(*l))
Out[66]: [(''B'', 3), (''A'', 2), (''A'', 1), (''I'', 1), (''J'', 1)]
In [4]: l = [(''B'', 3), (''A'', 2), (''A'', 1), (''I'', 1), (''J'', 1)]
In [5]: sorted(l, key=lambda (x,y):(-y,x))
Out[5]: [(''B'', 3), (''A'', 2), (''A'', 1), (''I'', 1), (''J'', 1)]