python python-3.x

python - Ordenar por mĂșltiples claves utilizando diferentes ordenamientos



python-3.x (3)

Posible duplicado:
Cómo escribir las funciones de las teclas de clasificación de Python para valores descendentes

En Python 3, es bastante fácil ordenar una lista de objetos lexicográficamente usando varias teclas. Por ejemplo:

items.sort(key = lambda obj: obj.firstname, obj.lastname)

El argumento reverse permite especificar si desea un orden ascendente o descendente. Pero, ¿qué haces en el caso en el que quieras ordenar por varias teclas, pero deseas ordenar usando el orden descendente para la primera clave y el orden ascendente para la segunda?

Por ejemplo, supongamos que tenemos un objeto con dos atributos, points y name , donde points es un int y name es un str . Queremos ordenar una lista de estos objetos por points en orden descendente (para que el objeto con el mayor número de puntos sea el primero), pero para los objetos con un número igual de points , queremos ordenarlos por name en orden alfabético ( ascendente ) orden.

¿Cómo se puede lograr esto?


Existe functools.cmp_to_key para convertir una función de comparación en una clave compatible con las funciones de clasificación. Esto se proporcionó para las clases que usaban una función de comparación en Python 2 y necesitaban ser convertidas a Python 3 que ya no las permite.

Editar: También hay una sugerencia en el wiki de Python bajo el encabezado Clasificar la estabilidad y Clasificaciones complejas para hacer el ordenamiento en múltiples pases, desde la clave menos significativa hasta la más significativa. Esto funciona porque se garantiza que la ordenación de Python es estable, por lo que el orden anterior se mantiene cuando se encuentran claves equivalentes.


No hay una forma incorporada de manejar esto. Para el caso general, debe ordenar dos veces: primero por la clasificación secundaria, luego por la clasificación primaria. Como @Mark Ransom mencionó en su comentario, en muchos casos las variables son numéricas, por lo que puede usar el valor negativo para cambiar el orden.

Si conoce el tipo de variable que está tratando de clasificar y cómo trabajar con ella, también podría escribir una función de tecla que devuelva un valor decreciente al aumentar las teclas. Vea este hilo para un ejemplo de cadenas. (Básicamente, tomas el negativo del valor numérico ASCII de los caracteres).

En Python 2, también podría usar una función cmp lugar de una tecla, pero esto probablemente hará que la clasificación sea más lenta. Si lo hará demasiado lento depende de qué tan grande y sin clasificar sea la lista. En Python 3, el argumento cmp se ha ido, pero como observa @Mark Ransom, puedes usar cmp_to_key .


items.sort(key = lambda obj: (obj.firstname, [(-ord(c) for c in obj.lastname)]))