¿Cuál es la diferencia entre `sorted (list)` vs `list.sort ()`?


194

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 no ordenado después de que list.sort()se haya realizado?

44
Tenga cuidado si llama (accidentalmente) 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"
smci

Respuestas:


316

sorted()devuelve una nueva lista ordenada, sin afectar la lista original. list.sort()ordena la lista en el lugar , mutando los índices de la lista y devuelve None(como todas las operaciones en el lugar).

sorted()funciona en cualquier iterable, no solo en listas. Cadenas, tuplas, diccionarios (obtendrá las claves), generadores, etc., devolviendo una lista que contiene todos los elementos, ordenados.

  • Úselo list.sort()cuando desee mutar la lista, sorted()cuando desee recuperar un nuevo objeto ordenado. Úselo sorted()cuando desee ordenar algo que sea iterable, no una lista todavía .

  • Para las listas, list.sort()es más rápido que sorted()porque no tiene que crear una copia. Para cualquier otro iterable, no tienes otra opción.

  • No, no puede recuperar las posiciones originales. Una vez que llamó, list.sort()el pedido original se ha ido.


66
En general, cuando una función de Python regresa None, es una señal de que las operaciones se realizan en su lugar, por eso, cuando desea imprimir list.sort(), devuelve None.
user1767754

45

¿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.sortcuando 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 sortedcuando 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 sortedversió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 sorteduna 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 sortedcuando necesite una nueva lista ordenada de los datos, y lo usaré list.sortcuando necesite ordenar una lista en el lugar, y dejar que eso determine mi uso.


44
La configuración del generador es agradable, pero no sacaría la conclusión de que rompiste un mito demasiado rápido. El hecho es que sorted()tiene que asignar un nuevo objeto de lista y copiar las referencias; El resto de las rutas de código son idénticas. Vea si puede ejecutar las mismas pruebas con listas más grandes. Compárelo con solo crear copias de listas y vea si puede replicar las diferencias que encontró, etc.
Martijn Pieters

11

La principal diferencia es que sorted(some_list)devuelve un nuevolist :

a = [3, 2, 1]
print sorted(a) # new list
print a         # is not modified

y some_list.sort(), ordena la lista en su lugar :

a = [3, 2, 1]
print a.sort() # in place
print a         # it's modified

Tenga en cuenta que como a.sort()no devuelve nada, print a.sort()se imprimirá None.


¿Se puede recuperar una lista de posiciones originales después de list.sort ()?

No, porque modifica la lista original.


1
print a.sort()No imprime nada.
Burhan Khalid

1
Se imprimirá None, lo aclararé.
Christian

1

La función .sort () almacena el valor de la nueva lista directamente en la variable de la lista; entonces la respuesta para su tercera pregunta sería NO. Además, si hace esto usando sorted (list), puede usarlo porque no está almacenado en la variable list. También a veces el método .sort () actúa como función, o dice que toma argumentos en él.

Debe almacenar el valor de sorted (list) en una variable explícitamente.

También para el procesamiento de datos cortos, la velocidad no tendrá diferencia; pero para largas listas; debe usar directamente el método .sort () para un trabajo rápido; pero nuevamente enfrentarás acciones irreversibles.


"La función .sort () almacena el valor de la nueva lista directamente en la variable de lista" ¿Eh? ¿Qué nueva lista? No hay una nueva lista. El list.sort()método ordena el objeto de la lista en el lugar.
PM 2Ring

Además, ¿qué se supone que significa esto? "A veces, el método .sort () actúa como función, o dice que toma argumentos en él".
PM 2Ring

Lo que quiero decir con nueva lista es la lista modificada y .sort () simplemente almacena esa lista modificada en esa misma variable.
Vicrobot

Sí, absolutamente a veces el .sort()método toma argumentos y actúa como función. También lo llamamos método porque es un atributo de tipo de datos de lista.
Vicrobot

Si hay algún tipo de error en mi concepto, dígame, lo buscaré y mejoraré mis conceptos, y mi respuesta también. Gracias
Vicrobot

1

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 sorteda esta lista, sortedhará una copia de la lista. (Lo que significa que su lista original permanecerá sin cambios).

Veamos.

sorted(nums)

devoluciones

[-3, 1, 4, 5, 7, 8, 9, 14]

Mirando de numsnuevo

nums

Vemos la lista original (sin alterar y NO ordenada). sortedno cambió la lista original

[1, 2, -3, 4, 8, 5, 7, 14]

Tomar la misma numslista y aplicarle la sortfunción cambiará la lista real.

Veamos.

Comenzando con nuestra numslista para asegurarnos, el contenido sigue siendo el mismo.

nums

[-3, 1, 4, 5, 7, 8, 9, 14]

nums.sort()

Ahora la lista de nums original ha cambiado y al mirar los nums vemos que nuestra lista original ha cambiado y ahora está ordenada.

nums
[-3, 1, 2, 4, 5, 7, 8, 14]

Gracias por mostrar el original vs. la copia con más profundidad
Brendan Metcalfe

0

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 dada 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 puede usar la función incorporada de Python sorted () para el mismo propósito. función ordenada regresar lista ordenada

 list=sorted(list, key=..., reverse=...)
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.