Al llamar al sort()
en una lista en Python, al pasar cmp=f
se ralentiza el orden. ¿Pasar reverse=True
afecta la eficiencia del género de alguna manera (o es idéntica a la clasificación sin inversión)?¿Pasa revertir = Verdadero cuando la clasificación de una lista en Python afecta la eficiencia?
Respuesta
El método sort()
es nativo, es decir, se implementa en el idioma del host en lugar de en Python. Al pasar una función en el argumento cmp
se fuerza a la implementación nativa a llamar a esa función y ejecutar código Python en cada iteración. Ahí es donde proviene el golpe de rendimiento.
Por otro lado, pasar True
en el argumento reverse
solo indica al algoritmo nativo que ordene los elementos en orden inverso. Si cmp
no está configurado, solo estará involucrado el código nativo, por lo que el rendimiento debería ser comparable al simple sort()
.
Por supuesto, la evaluación comparativa lo diría con certeza.
Supongo que no hay desaceleración debido a reverse=True
ya que el resultado podría simplemente construirse con decisiones invertidas en el camino. Si se comparan correctamente (gracias a Duncan), esta suposición se confirma:
In [18]: import random
In [57]: x = range(1000)
In [58]: random.shuffle(x)
In [59]: %timeit sorted(x)
1000 loops, best of 3: 341 us per loop
In [54]: x = range(1000)
In [55]: random.shuffle(x)
In [56]: %timeit sorted(x, reverse = True)
1000 loops, best of 3: 344 us per loop
He repetido esta prueba varias veces y con diferentes listas de tamaño (N = 10**3, 10**4, 10**5
) y recibieron resultados consistentes.
Creo que su punto de referencia está roto. Debería probar el tiempo 'ordenado (x)', de lo contrario, lo ordena una vez y luego simplemente el tiempo que toma ordenar o revertir la clasificación de una lista ordenada. Cuando intento un benchmark con 'sorted (x)' obtengo 4.41mS por loop y ninguna diferencia para el reverse contra 249uS/262uS para 'x.sort()' – Duncan
Gracias, @Duncan, tienes razón. Editando ... – unutbu
De mis puntos de referencia, parece que hay una pequeña diferencia:
import timeit
setup = """
import random
random.seed(1)
l = range(10000)
random.shuffle(l)
"""
run1 = """
sorted(l)
"""
run2 = """
sorted(l, reverse=True)
"""
n1 = timeit.timeit(run1, setup, number=10000)
n2 = timeit.timeit(run2, setup, number=10000)
print n1, n2
print (n2/n1 - 1)*100,"%"
Resultados en (en mi máquina):
38.8531708717 41.2889549732
6.26920286513 %
la misma corrida, pero para una lista de 1000 elementos:
2.80148005486 2.74061703682
-2.17253083528 %
# ...another round...
2.90553498268 2.86594104767
-1.36270722083 %
Ordenando la misma lista cada vez no prueba una diferencia, porque el tiempo de ordenamiento dependerá de la distribución de datos. –
Sorprendentemente, lleva más tiempo revertir-ordenar una lista. Las otras respuestas ya han demostrado esto con buenos puntos de referencia. Miré en la fuente y encontré el explanation in listobject.c
:
/* Reverse sort stability achieved by initially reversing the list,
applying a stable forward sort, then reversing the final result. */
if (reverse) {
if (keys != NULL)
reverse_slice(&keys[0], &keys[saved_ob_size]);
reverse_slice(&saved_ob_item[0], &saved_ob_item[saved_ob_size]);
}
Por lo tanto, para obtener una salida ordenada, la lista se invierte antes de la clasificación, a continuación, ordenadas, y finalmente invierte de nuevo. Invertir una lista es una operación O (n), por lo que pagará más y más por esto, más larga será la lista.
Esto sugiere que si usted está construyendo una función clave personalizada de todos modos, a continuación, se puede ahorrar tiempo para grandes listas negando directamente:
very_long_list.sort(key=lambda x, y: -cmp(x, y))
en lugar de utilizar reversed=True
:
very_long_list.sort(key=lambda x, y: cmp(x, y), reverse=True)
En este caso, puede pasar key=cmp
directamente en el segundo caso y guardar la llamada extra a través de la función lambda. Pero si tiene una expresión más grande, entonces esto podría dar sus frutos.
Tenga en cuenta que si simplemente niega la función de comparación, la ordenación invertida ya no será estable. Es por eso que Python hace la mezcla inversa/ordenar/invertir para mantener la estabilidad. – Duncan
+1 para hacer la exploración de código. Todavía estaba descargando la bola de alquitrán ... ;-) – GaretJax
@Duncan: ¿Estás seguro? No creo que sea cierto: por definición 'sort (key = f)' es estable para cualquier 'f', incluido el caso cuando' f' es una función de comparación negada. Parece que el código cpython hace doble inversión para que no tenga que negar los resultados de la función de comparación por razones de rendimiento, pero podría hacerlo y ser correcto. Lo que sería incorrecto es una clasificación estable mediante la tecla normal y luego la inversión (sin inversión antes de la clasificación). – sdcvvc
Tenga en cuenta que la cmp
arg a list.sort
y la función incorporada sorted
están en desuso en Python 2. x y ya no se permiten en 3. x, a causa de los malos resultados que dan, como usted ha notado . En su lugar, se supone que debe usar el key
arg para definir un orden de clasificación personalizado.
Realmente, obsoleto en todo 2.x? Tengo un libro de 2.3 y 2.4 días y está explicado y recomendado. – jrdioko
Bien, quédate con 2.3/2.4. –
- 1. ¿Cuánto afecta la indirección del puntero a la eficiencia?
- 2. lista de clasificación en python
- 3. Clasificación Python - Una lista de objetos
- 4. Eficiencia de utilizar una lista de Python como cola
- 5. Cómo revertir una lista?
- 6. ordenar una lista en Python usando el resultado de la clasificación de otra lista
- 7. cómo revertir una lista anónima en la plantilla de herramientas?
- 8. revertir una cadena en Python
- 9. ¿Cómo revertir una lista vinculada?
- 10. Eficiencia de la excepción cuando no se arroja nada
- 11. Python: iterar sobre la lista de artículos de diccionario vs sobre la eficiencia
- 12. por qué no puedo revertir una lista de lista en Python
- 13. La eficiencia al usar una estructura de big data en una función en Python
- 14. ¿Cuál es la mejor manera de ordenar la lista con parámetros de clasificación personalizados en Python?
- 15. Python lista que pasa como argumento
- 16. c Tratando de revertir una lista
- 17. Clasificación de archivos en una lista
- 18. Revertir una compilación de fusión de git, y luego revertir la revertir
- 19. Clasificación de lista basada en otra lista
- 20. La eficiencia de usar un pthread_rwlock cuando hay muchos lectores
- 21. convertir una lista plana en la lista de la lista en python
- 22. Clasificación de imágenes en python
- 23. ¿Cuál es la forma más limpia de hacer una clasificación más uniq en una lista de Python?
- 24. Eficiencia de la computación Pregunta
- 25. Retire la lista de la lista en Python
- 26. ¿Pasa cada elemento de una lista a una función que toma múltiples argumentos en Python?
- 27. ¿Cuál es la forma más rápida de revertir una lista separada por comas en vim?
- 28. deshacer o revertir argsort(), python
- 29. la eficiencia de la utilización CASO CUANDO ... no es nulo vs ISNULL/COALESCE
- 30. Lista de clasificación C# basada en otra lista
+0.75 para una pregunta interesante y útil, y +0.25 para el uso correcto de la palabra * affect *. –