Saltar al contenido
🐍 Curso de Python
/

Módulo 1 · Lección 24 de 59

Ordenar y buscar en listas

Ordenar en el sitio o en una lista nueva, cambiar el criterio de orden, localizar elementos y resumir una lista con una función.

⏱ 13 min de lectura

Una lista llega casi siempre en el orden en que se recogieron los datos, que rara vez es el orden en que quieres mostrarlos. Ordenar alfabéticamente un listado de nombres, poner los precios de menor a mayor o sacar la nota más alta son operaciones tan frecuentes que Python las trae resueltas.

Lo que sí tienes que decidir cada vez es si quieres reordenar la lista que tienes o obtener una lista nueva ordenada dejando la original en paz. Esa decisión es la que separa sort() de sorted(), y confundirlas es el error clásico de esta lección.

sort() ordena la lista en el sitio#

python
precios = [29.99, 189.00, 15.50, 45.00]

precios.sort()

print(precios)
Salida en pantalla
[15.5, 29.99, 45.0, 189.0]

La lista original ha cambiado. No hay ninguna lista nueva, y sort() no devuelve nada:

python
precios = [29.99, 189.00, 15.50]

resultado = precios.sort()

print(resultado)
print(precios)
Salida en pantalla
None
[15.5, 29.99, 189.0]

Con cadenas ordena alfabéticamente, pero con una salvedad que conviene ver:

python
nombres = ["marta", "Ana", "luis", "Álvaro"]

nombres.sort()

print(nombres)
Salida en pantalla
['Ana', 'luis', 'marta', 'Álvaro']

Las mayúsculas van antes que las minúsculas y las letras acentuadas se van al final, porque la comparación usa el código interno de cada carácter, no el orden del diccionario español. Se arregla con el parámetro key, unos apartados más abajo.

sorted() devuelve una lista nueva#

python
precios = [29.99, 189.00, 15.50, 45.00]

ordenados = sorted(precios)

print(f"nueva:    {ordenados}")
print(f"original: {precios}")
Salida en pantalla
nueva:    [15.5, 29.99, 45.0, 189.0]
original: [29.99, 189.0, 15.5, 45.0]

sorted() es una función, no un método, así que se escribe con la lista dentro de los paréntesis. La original queda intacta, y eso lo hace la opción más segura cuando solo quieres mostrar los datos ordenados.

lista.sort()sorted(lista)
Qué esMétodo de las listasFunción general
A la originalLa reordenaNo la toca
DevuelveNoneUna lista nueva
Se escribelista.sort()nueva = sorted(lista)
Funciona conSolo listasCualquier colección

Ese último punto importa: sorted() acepta cadenas, tuplas, conjuntos y diccionarios, y siempre te devuelve una lista.

python
print(sorted("python"))
print(sorted((3, 1, 2)))
Salida en pantalla
['h', 'n', 'o', 'p', 't', 'y']
[1, 2, 3]

De mayor a menor: reverse#

Los dos aceptan el parámetro reverse, que da la vuelta al criterio:

python
puntuaciones = [1200, 850, 3400, 2100]

print(sorted(puntuaciones, reverse=True))

puntuaciones.sort(reverse=True)
print(puntuaciones)
Salida en pantalla
[3400, 2100, 1200, 850]
[3400, 2100, 1200, 850]

Es lo que quieres para cualquier ranking: la puntuación más alta primero.

Cambiar el criterio: key#

Por defecto se ordena comparando los elementos entre sí. Con key le dices a Python qué mirar de cada elemento para compararlo. Se le pasa el nombre de una función, sin paréntesis.

Ordenar por longitud en vez de alfabéticamente:

python
palabras = ["murciélago", "sol", "ventana", "pez"]

print(sorted(palabras, key=len))
Salida en pantalla
['sol', 'pez', 'ventana', 'murciélago']

Lo que ha pasado es que Python ha aplicado len a cada palabra y ha ordenado por el número resultante: 3, 3, 7, 10. "sol" y "pez" empatan a tres letras, y en caso de empate se mantiene el orden que tenían en la lista original. Eso se llama orden estable y es una garantía de Python, no una casualidad.

Ordenar sin que las mayúsculas molesten:

python
nombres = ["marta", "Ana", "luis", "Pedro"]

print(sorted(nombres))                    # las mayúsculas van primero
print(sorted(nombres, key=str.lower))     # orden alfabético de verdad
Salida en pantalla
['Ana', 'Pedro', 'luis', 'marta']
['Ana', 'luis', 'marta', 'Pedro']

str.lower es el método lower que ya usabas, escrito en la forma "el método de la clase cadena", que es como se le pasa a key. Python lo aplica a cada elemento para decidir el orden, pero los elementos de la lista no se modifican: siguen con sus mayúsculas.

Se pueden combinar key y reverse:

python
palabras = ["sol", "murciélago", "ventana", "pez"]

print(sorted(palabras, key=len, reverse=True))
Salida en pantalla
['murciélago', 'ventana', 'sol', 'pez']

Dar la vuelta: reverse()#

No confundas el método reverse() con el parámetro reverse=True. El método invierte el orden actual de la lista, esté ordenada o no, y también trabaja en el sitio devolviendo None:

python
historial = ["inicio", "productos", "carrito", "pago"]

historial.reverse()

print(historial)
Salida en pantalla
['pago', 'carrito', 'productos', 'inicio']

Si lo que quieres es una lista nueva invertida, tienes el rebanado [::-1], que no toca la original:

python
historial = ["inicio", "productos", "carrito", "pago"]

print(historial[::-1])
print(historial)
Salida en pantalla
['pago', 'carrito', 'productos', 'inicio']
['inicio', 'productos', 'carrito', 'pago']

Buscar: index y count#

index te dice en qué posición está un valor, y count cuántas veces aparece:

python
colores = ["rojo", "verde", "azul", "verde", "verde"]

print(colores.index("azul"))
print(colores.index("verde"))      # solo la primera aparición
print(colores.count("verde"))
print(colores.count("morado"))     # no está: cero
Salida en pantalla
2
1
3
0

Resumir una lista con una función#

Estas cinco funciones convierten una lista entera en un solo valor, y te ahorran el bucle que escribiste a mano en la lección anterior:

python
temperaturas = [18.2, 24.5, 31.0, 27.8, 15.4]

print(f"suma:   {sum(temperaturas)}")
print(f"mínima: {min(temperaturas)}")
print(f"máxima: {max(temperaturas)}")
print(f"media:  {sum(temperaturas) / len(temperaturas):.2f}")
Salida en pantalla
suma:   116.9
mínima: 15.4
máxima: 31.0
media:  23.38

La media no tiene función propia: se calcula dividiendo la suma entre el número de elementos, y conviene darle formato con :.2f porque el resultado suele traer una cola de decimales innecesaria.

min y max también aceptan key, lo que los hace mucho más útiles:

python
palabras = ["sol", "murciélago", "ventana", "pez"]

print(min(palabras))                # alfabéticamente
print(max(palabras, key=len))       # la más larga
Salida en pantalla
murciélago
murciélago

Y luego hay dos que trabajan con condiciones, any y all:

python
notas = [7.5, 4.0, 9.25, 6.0]
comprobaciones = []

for nota in notas:
        comprobaciones.append(nota >= 5)

print(comprobaciones)
print(any(comprobaciones))    # ¿alguno es True?
print(all(comprobaciones))    # ¿todos son True?
Salida en pantalla
[True, False, True, True]
True
False

any responde "¿hay al menos uno?" y all responde "¿lo cumplen todos?". Hay al menos un aprobado, pero no han aprobado todos. En la próxima lección verás cómo escribir esa lista de comprobaciones en una sola línea, y entonces any y all se leerán como una frase.

Tabla de referencia#

OperaciónModificaDevuelve
lista.sort()SíNone
sorted(lista)NoLista nueva
lista.reverse()SíNone
lista[::-1]NoLista nueva
lista.index(x)NoPosición, o ValueError
lista.count(x)NoNúmero de apariciones
sum, min, maxNoUn número
any, allNoTrue o False

Un ejemplo completo#

ranking.py
jugadores = ["Marta", "ana", "Luis", "pedro", "Sara"]
puntos = [3400, 1200, 2100, 850, 2100]

print("Clasificación")
print("=" * 25)

for posicion, puntuacion in enumerate(sorted(puntos, reverse=True), start=1):
        jugador = jugadores[puntos.index(puntuacion)]
    print(f"{posicion}. {jugador:<8} {puntuacion:>6}")

print("=" * 25)
print(f"Jugadores:  {len(jugadores)}")
print(f"Total:      {sum(puntos)}")
print(f"Mejor:      {max(puntos)}")
print(f"Peor:       {min(puntos)}")
print(f"Media:      {sum(puntos) / len(puntos):.1f}")
print(f"Por nombre: {sorted(jugadores, key=str.lower)}")
Salida en pantalla
Clasificación
=========================
1. Marta      3400
2. Luis       2100
3. Luis       2100
4. ana        1200
5. pedro       850
=========================
Jugadores:  5
Total:      9650
Mejor:      3400
Peor:       850
Media:      1930.0
Por nombre: ['ana', 'Luis', 'Marta', 'pedro', 'Sara']

Mira la clasificación con cuidado: Sara aparece como Luis. El fallo es mío y es a propósito, para que veas el límite de este enfoque. Como Luis y Sara empatan a 2100 puntos, puntos.index(2100) devuelve siempre la primera aparición, así que Sara nunca sale. Mantener dos listas emparejadas y cruzarlas por el valor es frágil; la solución buena es guardar cada jugador con sus puntos en una sola estructura, y eso son los diccionarios de dentro de unas lecciones.