sorted() y sort() en Python: key=, reverse= y ordenar objetos propios

Python ofrece dos formas de ordenar: sorted() devuelve una nueva lista ordenada sin modificar el original, y list.sort() modifica la lista en sitio y devuelve None. Ambas comparten los parámetros key= y reverse=, que son la clave para cualquier ordenación no trivial.

sorted() vs sort()

numeros = [3, 1, 4, 1, 5, 9, 2, 6]

# sorted(): no modifica la original, devuelve nueva lista
ordenados = sorted(numeros)
print(ordenados)  # [1, 1, 2, 3, 4, 5, 6, 9]
print(numeros)    # [3, 1, 4, 1, 5, 9, 2, 6] — intacta

# sort(): modifica in-place, devuelve None
numeros.sort()
print(numeros)    # [1, 1, 2, 3, 4, 5, 6, 9]

# sorted() funciona con cualquier iterable; sort() solo con listas
print(sorted("python"))   # ['h', 'n', 'o', 'p', 't', 'y']
print(sorted((5, 3, 1)))  # [1, 3, 5]

El parámetro key=

frutas = ["naranja", "kiwi", "manzana", "pera", "uva"]

# Ordenar por longitud
print(sorted(frutas, key=len))
# ['kiwi', 'uva', 'pera', 'naranja', 'manzana']

# Ordenar sin distinguir mayúsculas/minúsculas
palabras = ["Python", "java", "Go", "RUST", "kotlin"]
print(sorted(palabras, key=str.lower))
# ['Go', 'java', 'kotlin', 'Python', 'RUST']

# Ordenar por el último carácter
print(sorted(frutas, key=lambda s: s[-1]))

Ordenar objetos propios

from dataclasses import dataclass

@dataclass
class Producto:
    nombre: str
    precio: float
    stock: int

productos = [
    Producto("Teclado", 89.99, 50),
    Producto("Ratón",   29.99, 100),
    Producto("Monitor", 349.0, 15),
    Producto("Auriculares", 59.99, 30),
]

# Por precio
por_precio = sorted(productos, key=lambda p: p.precio)
for p in por_precio:
    print(f"{p.nombre}: {p.precio}€")

# Con operator.attrgetter (más rápido que lambda para atributos)
from operator import attrgetter
por_stock = sorted(productos, key=attrgetter("stock"))

# Por precio descendente
mas_caros = sorted(productos, key=lambda p: p.precio, reverse=True)

Ordenar diccionarios

inventario = {"manzanas": 150, "peras": 80, "naranjas": 210, "kiwis": 45}

# Ordenar por clave
por_clave = dict(sorted(inventario.items()))
print(por_clave)

# Ordenar por valor descendente
por_cantidad = dict(sorted(inventario.items(), key=lambda x: x[1], reverse=True))
print(por_cantidad)
# {'naranjas': 210, 'manzanas': 150, 'peras': 80, 'kiwis': 45}

# Con operator.itemgetter
from operator import itemgetter
por_cantidad = dict(sorted(inventario.items(), key=itemgetter(1), reverse=True))

Ordenación multicriterio

empleados = [
    {"nombre": "Ana",   "dept": "tech",   "salario": 45000},
    {"nombre": "Luis",  "dept": "ventas", "salario": 38000},
    {"nombre": "María", "dept": "tech",   "salario": 52000},
    {"nombre": "Juan",  "dept": "ventas", "salario": 38000},
]

# Ordenar por departamento y luego por salario descendente
resultado = sorted(
    empleados,
    key=lambda e: (e["dept"], -e["salario"])
)

for e in resultado:
    print(f"{e['dept']}: {e['nombre']} ({e['salario']}€)")
# tech: María (52000€)
# tech: Ana (45000€)
# ventas: Luis (38000€) o Juan (38000€) — orden estable

# Con itemgetter para múltiples campos
from operator import itemgetter
por_dept_nombre = sorted(empleados, key=itemgetter("dept", "nombre"))

El algoritmo de Python (Timsort) es estable: elementos con la misma clave mantienen el orden relativo original. Eso permite ordenar en dos pasadas: primero por criterio secundario, luego por el principal, obteniendo el resultado correcto.

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP