Qual é a diferença entre sorted(list)
vs list.sort()
?
list.sort
altera a lista no local e retorna None
sorted
pega qualquer iterável e retorna uma nova lista, classificada.
sorted
é equivalente a esta implementação do Python, mas a função embutida do CPython deve ser executada de forma mensurável mais rápida, como está escrito em 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
quando usar qual?
- Use
list.sort
quando não desejar manter a ordem de classificação original (portanto, você poderá reutilizar a lista no local na memória.) E quando for o único proprietário da lista (se a lista for compartilhada por outro código e você para modificá-lo, você pode introduzir bugs onde essa lista é usada.)
- Use
sorted
quando desejar manter a ordem de classificação original ou quando desejar criar uma nova lista que apenas o código local possua.
As posições originais de uma lista podem ser recuperadas após list.sort ()?
Não - a menos que você tenha feito uma cópia, essas informações são perdidas porque a classificação é feita no local.
"E qual é mais rápido? E quanto mais rápido?"
Para ilustrar a penalidade de criar uma nova lista, use o módulo timeit, aqui está nossa configuração:
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
"""
E aqui estão nossos resultados para uma lista de 10000 números aleatoriamente organizados, como podemos ver aqui, refutamos um mito de despesas de criação de lista mais antigo :
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]
Após algum feedback, decidi que outro teste seria desejável com características diferentes. Aqui eu forneço a mesma lista ordenada aleatoriamente de 100.000 de comprimento para cada iteração 1.000 vezes.
import timeit
setup = """
import random
random.seed(0)
lst = list(range(100000))
random.shuffle(lst)
"""
Eu interpreto a diferença desse tipo maior proveniente da cópia mencionada por Martijn, mas não domina até o ponto indicado na resposta mais antiga e popular aqui, aqui o aumento no tempo é de apenas 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]
Também executei o procedimento acima em uma classificação muito menor e vi que a nova sorted
versão da cópia ainda leva cerca de 2% mais tempo de execução em uma espécie de comprimento 1000.
Poke também executou seu próprio código, eis o 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))
Ele encontrou uma classificação de 1000000 comprimentos ((executou 100 vezes) um resultado semelhante, mas apenas um aumento de 5% no tempo, eis a saída:
10000000 100
l = next(it); l.sort()
610.5015971539542
l = next(it); sorted(l)
646.7786222379655
Conclusão:
Uma lista grande e classificada com sorted
uma cópia provavelmente dominará as diferenças, mas a própria classificação domina a operação, e organizar seu código em torno dessas diferenças seria uma otimização prematura. Usaria sorted
quando necessitasse de uma nova lista ordenada de dados e usaria list.sort
quando precisasse ordenar uma lista no local e permitir que isso determinasse meu uso.
sorted()
em um argumento de cadeia, mas acho que é uma lista, você obter um resultado lista, não uma string :sorted("abcd", reverse=True)
dá['d', 'c', 'b', 'a']
não"dcba"