Ordenar listas en Python, con ejemplos


El proyecto de este post lo puedes descargar pulsando AQUI.

En el tutorial "List en Python, con ejemplos" hablamos del método "sort()" para la ordenación de los elementos de una lista que en ese caso los elementos eran datos atómicos y por tanto eran muy sencillos de ordenar. En este tutorial vamos a ver cómo ordenar elementos "no atómicos" (tuplas, objetos, etc.) de una lista o cómo ordenar una lista de strings a partir de un substring.

Recordemos en primer lugar el método "sort()":

nombreLista.sort(cmp=None, key=None, reverse=False)

Como vemos este método tiene 3 parámetros. El primero 'cmp' lo vamos a obviar ya que a este habría que pasarle una función de comparación de dos elementos y esto lo haremos con el segundo parámetro 'key' al que le indicaremos por que campo, valor, atributo, etc. queremos ordenar la lista. El tercer parámetro 'reverse' le indicaremos con un True o False si queremos que la ordenación sea de forma creciente (reverse=False) o decreciente (reverse=True). Por defecto sino definimos este parámetro la ordenación será de forma creciente.

Vamos a pasar con el primer ejemplo en el que vamos a tener una lista de tuplas:

# Lista de Tuplas
futbolistasTup = [(1, "Casillas"), (15, "Ramos"), (3, "Pique"), (5, "Puyol"), (11, "Capdevila"), (14, "Xabi Alonso"), (16, "Busquets"), (8, "Xavi Hernandez"), (18, "Pedrito"), (6, "Iniesta"), (7, "Villa")]

En este caso cada tupla contendrá en la primera posición el dorsal y en la segunda posición el nombre de los jugadores titulares de la selección Española que ganaron el mundial del 2010. En este primer ejemplo vamos a ordenar esta lista por el dorsal, es decir por la primera posición de la tupla. Para ello le indicamos al parámetro 'key' (con una función lambda) el valor por el que queremos ordenar la lista, que será la primera posición de cada una de las tuplas. Esto lo hacemos de la siguiente forma:

futbolistasTup.sort(key=lambda futbolista: futbolista[0])
print "Imprimimos las lista ordenada por dorsal:"
print futbolistasTup

Como salida a este fragmento de código tenemos la siguiente lista de tuplas ordenada por dorsal:

Imprimimos las lista ordenada por dorsal:
[(1, 'Casillas'), (3, 'Pique'), (5, 'Puyol'), (6, 'Iniesta'), (7, 'Villa'), (8, 'Xavi Hernandez'), (11, 'Capdevila'), (14, 'Xabi Alonso'), (15, 'Ramos'), (16, 'Busquets'), (18, 'Pedrito')]

Si quisiésemos ordenarlo por dorsal en orden decreciente solo tendríamos que pasale el parámetro 'reverse=True':

futbolistasTup.sort(key=lambda futbolista: futbolista[0], reverse=True)

Si ahora quisiésemos ordenar esta lista por nombre (en orden alfabético) habría que indicarle en la función lambda que lo compare por la segunda posición de la tupla:

futbolistasTup.sort(key=lambda futbolista: futbolista[1])
print "Imprimimos las lista ordenada por el nombre del jugador:"
print futbolistasTup

Como salida a este fragmento de código tenemos lo siguiente:

Imprimimos las lista ordenada por el nombre del jugador:
[(16, 'Busquets'), (11, 'Capdevila'), (1, 'Casillas'), (6, 'Iniesta'), (18, 'Pedrito'), (3, 'Pique'), (5, 'Puyol'), (15, 'Ramos'), (7, 'Villa'), (14, 'Xabi Alonso'), (8, 'Xavi Hernandez')]

Veamos ahora como trabajaríamos con una lista de Strings que contiene el dorsal y el nombre de los jugadores separados por un guión:

# Lista de Strings
futbolistas = ["1 - Casillas", "15 - Ramos", "3 - Pique", "5 - Puyol", "11 - Capdevila", "14 - Xabi Alonso", "16 - Busquets", "8 - Xavi Hernandez", "18 - Pedrito", "6 - Iniesta", "7 - Villa"]

Para este ejemplo vamos a ordenar la lista por el nombre del jugador alfabéticamente de forma decreciente. Para ello tenemos que definir en la función lambda que le pasamos al parámetro 'key' que ordene la lista por la segunda parte del String (el nombre) tras hacer un "split" del mismo por el caracter "-":

futbolistas.sort(key=lambda futbolista: futbolista.split("-")[1], reverse=True)
print "\nImprimimos las lista ordenada por el nombre del jugador:"
print futbolistas

Como salida a este fragmento de código tenemos lo siguiente:

Imprimimos las lista ordenada por el nombre del jugador:
['8 - Xavi Hernandez', '14 - Xabi Alonso', '7 - Villa', '15 - Ramos', '5 - Puyol', '3 - Pique', '18 - Pedrito', '6 - Iniesta', '1 - Casillas', '11 - Capdevila', '16 - Busquets']

Pasemos por último a ordenar una lista de objetos por un atributo determinado. Para ello vamos a definir la siguiente clase "Futbolista":

class Futbolista:

    def __init__(self, dorsal, nombre, demarcacion):
        self.dorsal = dorsal
        self.nombre = nombre
        self.demarcacion = demarcacion


    def __str__(self):
        return "%i - %s - %s" % (self.dorsal, self.nombre, self.demarcacion)

Como vemos cada objeto de la clase "Futbolista" tendrá 3 atributos (dorsal, nombre y demarcación) y accediendo a cada uno de estos atributos podremos ordenar una lista que contenga objetos de esta clase. Vamos a ver un ejemplo: Nos creamos una lista llamada "futbolistasOb" que contendrá los siguientes objetos:

from Futbolista import Futbolista

futbolistasOb = list()
futbolistasOb.append(Futbolista(1,'Casillas','Portero'))
futbolistasOb.append(Futbolista(15,'Ramos','Lateral Derecho'))
futbolistasOb.append(Futbolista(3,'Pique','Central'))
futbolistasOb.append(Futbolista(5,'Puyol','Central'))
futbolistasOb.append(Futbolista(11,'Capdevila','Lateral Izquierdo'))
futbolistasOb.append(Futbolista(14,'Xabi Alonso','Medio Centro'))
futbolistasOb.append(Futbolista(16,'Busquets','Medio Centro'))
futbolistasOb.append(Futbolista(8,'Xavi Hernandez','Centro Campista'))
futbolistasOb.append(Futbolista(18,'Pedrito','Interior Izquierdo'))
futbolistasOb.append(Futbolista(6,'Iniesta','Interior Derecho'))
futbolistasOb.append(Futbolista(7,'Villa','Delantero'))

Para ordenar esta lista de objetos de la clase "Futbolista" por el atributo dorsal, tenemos que "decirle" a la función lambda del parámetro 'key' que el campo de ordenación es el atributo dorsal (futbolista.dorsal). Esto lo hacemos de la siguiente forma:

futbolistasOb.sort(key=lambda futbolista: futbolista.dorsal)
print "Futbolistas ordenados por el atributo Dorsal"
for i in futbolistasOb:
    print i

Como salida a este fragmento de código tenemos lo siguiente:

Futbolistas ordenados por el atributo Dorsal
1 - Casillas - Portero
3 - Pique - Central
5 - Puyol - Central
6 - Iniesta - Interior Derecho
7 - Villa - Delantero
8 - Xavi Hernandez - Centro Campista
11 - Capdevila - Lateral Izquierdo
14 - Xabi Alonso - Medio Centro
15 - Ramos - Lateral Derecho
16 - Busquets - Medio Centro
18 - Pedrito - Interior Izquierdo

De igual forma (y viendo los ejemplos anteriores) podemos ordenar también a los futbolistas por el nombre; que en este caso lo haremos de forma descendente. Para ello le indicamos a la función lambda que lo haga por el atributo 'nombre' y con la opción de 'reverse=True':

futbolistasOb.sort(key=lambda futbolista: futbolista.nombre, reverse=True)
print "Futbolistas ordenados descendentemente por el atributo Nombre"
for i in futbolistasOb:
    print i

Como salida a este fragmento de código tenemos lo siguiente:

Futbolistas ordenados descendentemente por el atributo Nombre
8 - Xavi Hernandez - Centro Campista
14 - Xabi Alonso - Medio Centro
7 - Villa - Delantero
15 - Ramos - Lateral Derecho
5 - Puyol - Central
3 - Pique - Central
18 - Pedrito - Interior Izquierdo
6 - Iniesta - Interior Derecho
1 - Casillas - Portero
11 - Capdevila - Lateral Izquierdo
16 - Busquets - Medio Centro

En resumen, se ha explicado en esta entrada todo lo necesario para ordenar una lista en función de un determinado elemento, substring, atributo, etc. Lo importante de todo esto es saber que se le debe de indicar correctamente por medio del parámetro 'key' el campo por el que se quiere ordenar por medio de una función lambda que será la encargada de acceder (bien sea con un split, indicando la posición de una tupla, lista, diccionario, etc, atributo de un objeto, …) al elemento por el que se ha de ordenar.

Comparte esta entrada en:
Safe Creative #1401310112503
Ordenar listas en Python, con ejemplos por "www.jarroba.com" esta bajo una licencia Creative Commons
Reconocimiento-NoComercial-CompartirIgual 3.0 Unported License.
Creado a partir de la obra en www.jarroba.com

17 thoughts on “Ordenar listas en Python, con ejemplos”

  1. aplausos!!
    la mejor explicación que he encontrado…. simplemente genial!
    se agradece su solidaridad.

  2. La función sort.() ya dejó de funcionar para la versión 3.7 de python, deberías actualizar tu información, ya que tanto a mí como a otros nos ha sido de gran ayuda todo este tiempo, muchas gracias.

    1. Muchas gracias Fabián por la indicación, lo tendremos en cuenta para una futura revisión del artículo.
      Es cierto que en Python 3 se recomienda la utilización de las funciones incorporadas (built-in) como sorted() https://docs.python.org/3/library/functions.html#sorted y efectivamente hay muchas que solo se permite el uso de las funciones incorporadas desde Python3 como next(obj) en vez de obj.__next__(). De momento obj.sort() sigue siendo válido como se comenta en https://docs.python.org/3.7/howto/sorting.html y no hay aviso de que vaya a quedar obsoleto https://docs.python.org/3/library/stdtypes.html?highlight=sort#list.sort
      ¿Cuál es recomendable utilizar? Personalmente uso y recomiendo utilizar sorted(obj_iterable) en vez de obj_iterable.sort(), pues las funciones de los objetos tienden a desaparecer en las futuras versiones y por seguir un mismo «estándar». Por otro lado, se siguen manteniendo ambas funciones en Python 3.7 https://docs.python.org/3/whatsnew/3.7.html.
      Lo que puede llevar a confusión es que la función sorted(lista) devuelve la lista ordenada y lista.sort() ordena el objeto y no lo devuelve (es decir que «lista = lista.sort()» devuelve None, con lo que solo hay que llamar a «lista.sort()»).
      Un ejemplo probado en Python 3.7.3 (default, Apr 24 2019, 15:29:51):
      >>> # Probar SORT:
      >>> milist = [2, 1, 3]
      >>> milist.sort()
      >>> milist
      [1, 2, 3]
      >>> # Probar SORTED:
      >>> milist = [2, 1, 3]
      >>> sorted(milist)
      [1, 2, 3]

  3. Hola. Tengo un problema con la ordenación de una lista de cadenas con números. Te paso un ejemplo para que veas:

    [‘/data/programs/oms/OMSDomain/bin/OMSDomain.1.99.100’, ‘/data/programs/oms/OMSDomain/bin/OMSDomain.1.99.101’, ‘/data/programs/oms/OMSDomain/bin/OMSDomain.1.99.51’, ‘/data/programs/oms/OMSDomain/bin/OMSDomain.1.99.52’]

    Como ves me ordena 1.99.100 y 101 bien, pero antes que la 51 etc… es como si leyera el 1 solo y luego el 5. Podrías decirme cómo solucionar esto?
    Muchas gracias!

    1. Al ser srings te lo ordena en orden digamos que «alfabético». Por ejemplo, los grupos de dos y tres letras te los ordenaría: AA, ABC, BB, BCD (Si te fijas en la ordenación alfabética, primero ordena las «As» luego las «Bs» y así con todas, por lo que le da igual cuántas letras tenga cada palabra, las va a ordenar siempre en orden alfabético). Con los números como strings pasa lo mismo, los ordenaría en orden «alfabético» (ordena por el número ASCII que representa cada carácter) por ejemplo: «10», «100», «50», «500». Si quieres que los ordene como números: 10, 50, 100, 500. Para conseguir esto, lo que hay que hacer es extraer lo números del string, convertirlos en números (Por ejemplo, Integer) y ordenarlos siendo números.

      Dentro del compare() es donde tienes que hacer los cálculos (añadiremos el método getInt() para extraer el número del texto y poder ordenarlo por este número), por ejemplo:

      List<String> miListado = Arrays.asList("/data/programs/oms/OMSDomain/bin/OMSDomain.1.99.100", "/data/programs/oms/OMSDomain/bin/OMSDomain.1.99.101", /data/programs/oms/OMSDomain/bin/OMSDomain.1.99.51", /data/programs/oms/OMSDomain/bin/OMSDomain.1.99.52");
      Collections.sort(miListado, new Comparator() {
      public int compare(String s1, String s2) {
      return getInt(s1) - getInt(s2);
      }

      int getInt(String s) {
      // Elimina los que no sean dígitos y los agrupa en uno solo. Por ejemplo, "1.99.100" pasará a 199100 que convertido a Integer se puede ordenar como número
      String num = s.replaceAll("\\D+", "");
      // Intenta convertir el número encontrado a Integer siempre que se haya encontrado alguno, sino devuelve 0
      return num.isEmpty() ? 0 : Integer.parseInt(num);
      }
      });

  4. Y si en vez de tuplas, quiero ordenarlo por 3 claves de un diccionario??

    Es decir, que ordene por la clave1, despues la clave2 y despues la clave3??

    Me explico??

  5. Estimados programadores deseo saber como leer un archivo y ordenarlo alfabeticamente me dicen cual es el metodo en python 2.7 gracias

  6. Hola! yo tengo una duda que la pondre como ejemplo. Imagina tengo una lista en la que cada elemento de esa lista es otra lista con un atributo del color de camisetas y la cantidad de esas camisetas: [[«azul,3],[«verde»,1],[«amarillo», 1],[«violeta»,3],[«rosado»,0]] y quiero ordenarla de mayor cantidad a menor cantidad pero si es que son la misma cantidad, se ordena por abecedario. este ejemplo quedaria así: [[«azul,3],[«violeta»,3],[«amarillo», 1],[«verde»,1],[«rosado»,0]]. lo que se me ocurre es utilizar sort() para primero ordenarlo por cantidad, pero no se me ocurre como ordenarlo a partir de cantidad y abecedario al mismo tiempo. Espero me haya explicado bien.

    1. Lo que quieres hacer es una ordenación múltiple. Para ello lo más sencillo es por cada elementos obtener como clave una tupla de primero el valor que va a ser el criterio principal de ordenación y luego el segundo (de esta manera primero se a ordenar por le primer valor y luego por el segundo). Un ejemplo puede ser:

      mi_lista = [[“azul,3],[“verde”,1],[“amarillo”, 1],[“violeta”,3],[“rosado”,0]]
      futbolistas.sort(key=lambda lista_interna: (lista_interna[1], lista_interna[0]))

  7. Hola, ¿cómo estas?
    Tengo un problema con tú código y lo expongo a continuación:
    Quiero hacer un menú para que el operador pueda elegir porque campo ordenar.
    traductorOb.sort(key=lambda Traductor: Traductor.espaniol)
    es posible poner en una variable la opción ==> Traductor.espaniol

    Saludos desde Argentina-Santa Fe-Arequito

    1. Sí puedes poner en una variable el valor con el que ordenar.
      Para el ejemplo:

      valor_por_el_que_ordenar = 1
      futbolistasTup.sort(key=lambda futbolista: futbolista[valor_por_el_que_ordenar])

      Puede que te aclare más si desgranamos el lambda:


      def metodo(valor_del_listado):
      # El valor del listado es una tupla como por ejemplo: (3, ‘Pique’), donde podemos acceder a la posición 0 o 1 para tomarla como criterio de ordenación
      return valor_del_listado[valor_por_el_que_ordenar]

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Uso de cookies

Este sitio web utiliza cookies para que usted tenga la mejor experiencia de usuario. Si continúa navegando está dando su consentimiento para la aceptación de las mencionadas cookies y la aceptación de nuestra política de cookies

ACEPTAR
Aviso de cookies