¿Cuál es la diferencia entre sorted(list)
vs list.sort()
?
list.sort
muta la lista en el lugar y devuelve None
sorted
toma cualquier iterable y devuelve una nueva lista, ordenada.
sorted
es equivalente a esta implementación de Python, pero la función incorporada de CPython debería ejecutarse considerablemente más rápido como está escrito en C:
def sorted(iterable, key=None):
new_list = list(iterable) # make a new list
new_list.sort(key=key) # sort it
return new_list # return it
cuando usar cual?
- Úselo
list.sort
cuando no desee retener el orden de clasificación original (por lo tanto, podrá reutilizar la lista en el lugar en la memoria) y cuando sea el único propietario de la lista (si la lista es compartida por otro código y usted mutarlo, podría introducir errores donde se usa esa lista).
- Úselo
sorted
cuando desee conservar el orden de clasificación original o cuando desee crear una nueva lista que solo posea su código local.
¿Se pueden recuperar las posiciones originales de una lista después de list.sort ()?
No, a menos que haya hecho una copia usted mismo, esa información se pierde porque la clasificación se realiza en el lugar.
"¿Y cuál es más rápido? ¿Y cuánto más rápido?"
Para ilustrar la penalización de crear una nueva lista, use el módulo timeit, aquí está nuestra configuración:
import timeit
setup = """
import random
lists = [list(range(10000)) for _ in range(1000)] # list of lists
for l in lists:
random.shuffle(l) # shuffle each list
shuffled_iter = iter(lists) # wrap as iterator so next() yields one at a time
"""
Y aquí están nuestros resultados para una lista de 10000 enteros dispuestos al azar, como podemos ver aquí, hemos refutado un mito de gastos de creación de listas más antiguo :
Python 2.7
>>> timeit.repeat("next(shuffled_iter).sort()", setup=setup, number = 1000)
[3.75168503401801, 3.7473005310166627, 3.753129180986434]
>>> timeit.repeat("sorted(next(shuffled_iter))", setup=setup, number = 1000)
[3.702025591977872, 3.709248117986135, 3.71071034099441]
Python 3
>>> timeit.repeat("next(shuffled_iter).sort()", setup=setup, number = 1000)
[2.797430992126465, 2.796825885772705, 2.7744789123535156]
>>> timeit.repeat("sorted(next(shuffled_iter))", setup=setup, number = 1000)
[2.675589084625244, 2.8019039630889893, 2.849375009536743]
Después de algunos comentarios, decidí que sería deseable otra prueba con diferentes características. Aquí proporciono la misma lista ordenada aleatoriamente de 100,000 de longitud para cada iteración 1,000 veces.
import timeit
setup = """
import random
random.seed(0)
lst = list(range(100000))
random.shuffle(lst)
"""
Interpreto la diferencia de este tipo más grande que proviene de la copia mencionada por Martijn, pero no domina hasta el punto establecido en la respuesta más popular más antigua aquí, aquí el aumento en el tiempo es solo del 10%
>>> timeit.repeat("lst[:].sort()", setup=setup, number = 10000)
[572.919036605, 573.1384446719999, 568.5923951]
>>> timeit.repeat("sorted(lst[:])", setup=setup, number = 10000)
[647.0584738299999, 653.4040515829997, 657.9457361929999]
También ejecuté lo anterior en un tipo mucho más pequeño, y vi que la nueva sorted
versión de copia todavía tarda aproximadamente un 2% más de tiempo de ejecución en una especie de 1000 de longitud.
Poke también ejecutó su propio código, aquí está el código:
setup = '''
import random
random.seed(12122353453462456)
lst = list(range({length}))
random.shuffle(lst)
lists = [lst[:] for _ in range({repeats})]
it = iter(lists)
'''
t1 = 'l = next(it); l.sort()'
t2 = 'l = next(it); sorted(l)'
length = 10 ** 7
repeats = 10 ** 2
print(length, repeats)
for t in t1, t2:
print(t)
print(timeit(t, setup=setup.format(length=length, repeats=repeats), number=repeats))
Encontró para el orden de longitud 1000000, (corrió 100 veces) un resultado similar, pero solo un aumento del tiempo del 5%, aquí está el resultado:
10000000 100
l = next(it); l.sort()
610.5015971539542
l = next(it); sorted(l)
646.7786222379655
Conclusión:
Una lista de gran tamaño que se ordena con sorted
una copia probablemente dominará las diferencias, pero la ordenación en sí misma domina la operación, y organizar su código en torno a estas diferencias sería una optimización prematura. Lo usaría sorted
cuando necesite una nueva lista ordenada de los datos, y lo usaré list.sort
cuando necesite ordenar una lista en el lugar, y dejar que eso determine mi uso.
sorted()
a un argumento de cadena pero piensa que es una lista, obtiene un resultado de la lista, no una cadena :sorted("abcd", reverse=True)
da['d', 'c', 'b', 'a']
no"dcba"