669 votos

¿Cómo ordenar una lista de objetos en Python, basado en un atributo de los objetos?

Tengo una lista de objetos de Python que me gustaría ordenar por un atributo de los objetos mismos. La lista parece:

>>> ut
[<Tag: 128>, <Tag: 2008>, <Tag: <>, <Tag: actionscript>, <Tag: addresses>, <Tag: aes>, <Tag: ajax> ...]

Cada objeto tiene un recuento:

>>> ut[1].count
1L

Necesito ordenar la lista por número de cuenta descendente.

He visto varios métodos para esto, pero estoy buscando mejores prácticas en Python.

1120voto

Triptych Puntos 70247
# To sort the list in place...
ut.sort(key=lambda x: x.count, reverse=True)

# To return a new list, use the sorted() built-in function...
newlist = sorted(ut, key=lambda x: x.count, reverse=True)

clasificación por llaves»

74voto

tzot Puntos 32224

Una forma que puede ser más rápida, especialmente si su lista tiene un montón de discos, es usar operator.attrgetter("count") . Sin embargo, esto podría ejecuta en una versión anterior operador de Python, así que sería bueno tener un mecanismo de suplencia. Tal vez quieras hacer lo siguiente, entonces:

try: import operator
except ImportError: cmpfun= lambda x: x.count # use a lambda if no operator module
else: cmpfun= operator.attrgetter("count") # use operator since it's faster than lambda

ut.sort(key=cmpfun, reverse=True) # sort in-place

58voto

Jose M Vidal Puntos 3456

Los lectores deben notar que la clave= método:

ut.sort(key=lambda x: x.count, reverse=True)

es muchas veces más rápido que agregar rica operadores de comparación para los objetos. Me sorprendió leer esto (página 485 de "Python en una cáscara de Nuez"). Se puede confirmar mediante la ejecución de pruebas sobre este pequeño programa:

#!/usr/bin/env python
import random

class C:
    def __init__(self,count):
        self.count = count

    def __cmp__(self,other):
        return cmp(self.count,other.count)

longList = [C(random.random()) for i in xrange(1000000)] #about 6.1 secs
longList2 = longList[:]

longList.sort() #about 52 - 6.1 = 46 secs
longList2.sort(key = lambda c: c.count) #about 9 - 6.1 = 3 secs

Mi, muy mínimo, las pruebas demuestran que el primer tipo es más de 10 veces más lento, pero el libro dice que es sólo de alrededor de 5 veces más lento en general. La razón por la que dicen que es debido a la elevada optimiza el tipo de algoritmo utilizado en python (timsort).

Aun asi, es muy raro que .sort(lambda) es más rápido que el viejo y simple .sort(). Espero que arreglar eso.

15voto

muhuk Puntos 6526

Se parece mucho a una lista de instancias de modelo de Django ORM.

¿Por qué no ordenarlos en consulta como esta:

ut = Tag.objects.order_by('-count')

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X