¿Cuál es la diferencia entre `ordenado (lista)` y `list.sort()`?
list.sort()
ordena la lista y reemplaza la lista original, mientras que sorted(list)
devuelve una copia ordenada de la lista, sin cambiar la lista original.
- ¿Cuándo se prefiere uno sobre el otro?
- ¿Cuál es más eficiente? ¿Por cuanto?
- ¿Se puede revertir una lista al estado sin ordenar después de
list.sort()
haberla realizado?
Utilice ¿Por qué estas operaciones de lista (métodos) devuelven Ninguno, en lugar de la lista resultante? para cerrar preguntas en las que OP ha asignado inadvertidamente el resultado de .sort()
, en lugar de usar sorted
o una declaración separada. Una depuración adecuada revelaría que .sort()
había regresado None
, momento en el que "¿por qué?" es la pregunta que queda.
sorted()
devuelve una nueva lista ordenada, sin afectar la lista original. list.sort()
ordena la lista in situ , muta los índices de la lista y devuelve None
(como todas las operaciones in situ).
sorted()
funciona en cualquier iterable, no solo en listas. Cadenas, tuplas, diccionarios (obtendrás las claves), generadores, etc., que devuelven una lista que contiene todos los elementos, ordenados.
Úselo
list.sort()
cuando desee mutar la lista,sorted()
cuando desee recuperar un nuevo objeto ordenado. Úselosorted()
cuando desee ordenar algo que sea iterable, no una lista todavía .Para listas,
list.sort()
es más rápidosorted()
porque no es necesario crear una copia. Para cualquier otro iterable, no tienes otra opción.No, no puedes recuperar las posiciones originales. Una vez que llamaste,
list.sort()
el pedido original desapareció.
¿Cuál es la diferencia entre
sorted(list)
vslist.sort()
?
list.sort
muta la lista en el lugar y devuelveNone
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 tal como está escrita 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
¿Cuándo usar cuál?
- Úselo
list.sort
cuando no desee conservar el orden de clasificación original (por lo tanto, podrá reutilizar la lista in situ en la memoria) y cuando sea el único propietario de la lista (si la lista es compartida por otro código y usted mutárselo, podría introducir errores cuando se use 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 usted mismo haya hecho una copia, esa información se pierde porque la clasificación se realiza in situ.
"¿Y cuál es más rápido? ¿Y cuánto más rápido?"
Para ilustrar la penalidad 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 ordenados aleatoriamente. Como podemos ver aquí, hemos refutado un antiguo mito de gastos de creación de listas :
Pitón 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]
Pitón 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 características diferentes. 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 que la diferencia de este tipo más grande proviene de la copia mencionada por Martijn, pero no domina hasta el punto indicado en la respuesta más antigua y popular aquí, aquí el aumento en el tiempo es solo de aproximadamente el 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 orden mucho más pequeño y vi que la nueva sorted
versión de copia todavía requiere aproximadamente un 2 % más de tiempo de ejecución en un tipo de longitud de 1000.
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 una clasificación de 1000000 de longitud (ejecutó 100 veces) un resultado similar, pero solo un aumento del 5% en el tiempo, 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 mientras sorted
se realiza una copia probablemente dominará las diferencias, pero la clasificación en sí 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 necesito una nueva lista ordenada de datos, y lo usaría list.sort
cuando necesito ordenar una lista en el lugar y dejar que eso determine mi uso.
Aquí hay algunos ejemplos simples para ver la diferencia en acción:
Vea la lista de números aquí:
nums = [1, 9, -3, 4, 8, 5, 7, 14]
Al llamar sorted
a esta lista, sorted
se hará una copia de la misma. (Lo que significa que su lista original permanecerá sin cambios).
Vamos a ver.
sorted(nums)
devoluciones
[-3, 1, 4, 5, 7, 8, 9, 14]
mirando de nums
nuevo
nums
Vemos la lista original (inalterada y NO ordenada). sorted
no cambió la lista original
[1, 2, -3, 4, 8, 5, 7, 14]
Tomar la misma nums
lista y aplicarle la sort
función cambiará la lista real.
Vamos a ver.
Comenzando con nuestra nums
lista para asegurarnos, el contenido sigue siendo el mismo.
nums
[-3, 1, 4, 5, 7, 8, 9, 14]
nums.sort()
Ahora la lista de números original ha cambiado y al mirar los números vemos que nuestra lista original ha cambiado y ahora está ordenada.
nums
[-3, 1, 2, 4, 5, 7, 8, 14]
Nota: La diferencia más simple entre sort() y sorted() es: sort() no devuelve ningún valor, mientras que sorted() devuelve una lista iterable.
sort() no devuelve ningún valor.
El método sort() simplemente ordena los elementos de una lista determinada en un orden específico: ascendente o descendente sin devolver ningún valor.
La sintaxis del método sort() es:
list.sort(key=..., reverse=...)
Alternativamente, también puedes usar la función incorporada de Python sorted() para el mismo propósito. función ordenada devolver lista ordenada
list=sorted(list, key=..., reverse=...)