📊 Ordenación Avanzada
Los problemas de ordenación multi-criterio son los más comunes en nivel medio-avanzado.
Dominando sorted() con key resuelves muchos problemas rápido.
🔑 El parámetro key
# Ordenar strings por longitud
palabras = ["hola", "a", "python", "es"]
sorted(palabras, key=len)
# ['a', 'es', 'hola', 'python']
# Ordenar por último carácter
sorted(palabras, key=lambda x: x[-1])
# Ordenar números por valor absoluto
nums = [3, -5, 1, -2]
sorted(nums, key=abs)
# [1, -2, 3, -5]
📋 Ordenación multi-criterio
El truco: Devuelve una tupla. Python compara elemento por elemento.
estudiantes = [
("Ana", 85, 20), # (nombre, nota, edad)
("Luis", 92, 19),
("Eva", 85, 21),
("Pedro", 92, 20)
]
# Por nota (descendente), luego por edad (ascendente)
resultado = sorted(estudiantes, key=lambda x: (-x[1], x[2]))
# [('Luis', 92, 19), ('Pedro', 92, 20), ('Ana', 85, 20), ('Eva', 85, 21)]
El signo negativo:
-x[1] invierte el orden (de mayor a menor).
Solo funciona con números, no con strings.
🏅 Ejemplo clásico: Medallero olímpico
Problema: Ordenar países por oro (desc), luego plata (desc), luego bronce (desc), luego nombre (asc).
n = int(input())
paises = []
for _ in range(n):
partes = input().split()
nombre = partes[0]
oro = int(partes[1])
plata = int(partes[2])
bronce = int(partes[3])
paises.append((nombre, oro, plata, bronce))
# Ordenar: más oro primero, empate → más plata, etc.
resultado = sorted(paises, key=lambda x: (-x[1], -x[2], -x[3], x[0]))
for p in resultado:
print(p[0], p[1], p[2], p[3])
📝 Ordenar strings descendente
Como no puedes usar - con strings, hay dos opciones:
# Opción 1: reverse=True (si TODOS los criterios son descendentes)
sorted(nombres, reverse=True)
# Opción 2: Ordenar en dos pasos
# Primero por criterio secundario, luego por primario (stable sort)
datos = sorted(datos, key=lambda x: x.nombre) # asc por nombre
datos = sorted(datos, key=lambda x: -x.puntos) # desc por puntos
🎯 Patrón: Top N elementos
# Los 3 estudiantes con mejor nota
top_3 = sorted(estudiantes, key=lambda x: -x[1])[:3]
# Los 5 productos más baratos
baratos = sorted(productos, key=lambda x: x.precio)[:5]
📊 Ordenar diccionarios
puntos = {"Ana": 85, "Luis": 92, "Eva": 78}
# Por valor (puntos), descendente
ranking = sorted(puntos.items(), key=lambda x: -x[1])
# [('Luis', 92), ('Ana', 85), ('Eva', 78)]
# Por clave (nombre), ascendente
alfabetico = sorted(puntos.items(), key=lambda x: x[0])
# [('Ana', 85), ('Eva', 78), ('Luis', 92)]
✅ Ejercicio de práctica
Problema: Lee N líneas con nombre y 3 notas. Ordena por media descendente,
empates por nombre ascendente. Muestra nombre y media con 2 decimales.
👁️ Ver solución
n = int(input())
alumnos = []
for _ in range(n):
partes = input().split()
nombre = partes[0]
notas = [float(partes[i]) for i in range(1, 4)]
media = sum(notas) / 3
alumnos.append((nombre, media))
# Ordenar por media desc, nombre asc
resultado = sorted(alumnos, key=lambda x: (-x[1], x[0]))
for nombre, media in resultado:
print(f"{nombre} {media:.2f}")