[Python-es] Ordenar objetos de una lista por un atributo

José Alejandro Pérez Rubio perezj en si.uji.es
Lun Jun 24 08:57:11 CEST 2002


On Mon, 24 Jun 2002, [iso-8859-15] Tomás Javier Robles Prado wrote:

> Hola a todos,
> 
> 	Hay algún modo sencillo de ordenar los elementos de una lista de objetos por 
> un campo en particular?
> 	He visto que sort admite como parámetro una función:
> 	sort(...)
>   		L.sort([cmpfunc]) -- sort *IN PLACE*; if given, cmpfunc(x, y) -> -1, 0, 1
> pero no tengo claro cómo usarlo, y qué representan esos x e y
> 
> 	¿Existe algúm método rápido o me meto con un algoritmo de ordenación? Si 
> sirve de algo, el campo por el que ordeno es una cadena.
> 
> Gracias

Hasta lo que yo se, creo que tiene dos alternativas:

- La primera añadir a la clase de objetos que desea ordenar el metodo __cmp__
  Suponiendo que el nombre de la class es Foo y el nombre del campo por el
  que desea ordenar es Name ...

  class Foo ....



    def __cmp__( self, other ) :

      if self.Name < other.Name :
        rst = -1
      elif self.Name > other.Name :
        rst = 1
      else :
        rst = 0

      return rst


  con esto podria hacer: 

  >>> lst = [ obj1, obj2, obj3 ]
  >>> lst.sort()
  Y lst quedaria ordenada por el atributo Name

- La segunda alternativa consiste en crear una funcion de ordenacion para usar
  con sort. Esto seria ...

 
  def compara( x, y ) :

    # x e y son objetos de los que se desea ordenar

    if self.Name < other.Name :
      rst = -1
    elif self.Name > other.Name :
      rst = 1
    else :
      rst = 0

    return rst

  con esto podria hacer: 

  >>> lst = [ obj1, obj2, obj3 ]
  >>> lst.sort( compara )
  Y lst quedaria ordenada por el atributo Name


La eleccion de una u otra forma quiza sea mas circunstancial que otra cosa. 
En condiciones normales la primera parece mas general ... pero la segunda 
puede dar un buen resultado en la mayoria de casos, sobre todo cuando la
implementacion de la clase Foo (en este ejemplo) no esta accesible o no 
resulta sencillo modificarla.

Se me ocurre alguna forma mas divertida pero ... parece menos eficiente :-)

lst_ord = [ (i.Name, i) for i in lst ]
lst_ord.sort()
lst_ord = [ i[1] for i in lst_ord ]



Un saludo





Más información sobre la lista de distribución Python-es