Qual é a diferença entre `classificado (lista)` vs `lista.sort ()`?

194

list.sort()classifica a lista e substitui a lista original, enquanto sorted(list)retorna uma cópia classificada da lista, sem alterar a lista original.

  • Quando um prefere o outro?
  • Qual é mais eficiente? Por quanto?
  • Uma lista pode ser revertida para o estado não classificado após a list.sort()execução?
alvas
fonte
4
Cuidado se receber chamadas (acidentalmente) 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', 'c', 'b', 'a']não"dcba"
SMCI

Respostas:

316

sorted()retorna uma nova lista classificada, deixando a lista original inalterada. list.sort()classifica a lista no local , modificando os índices da lista e retorna None(como todas as operações no local).

sorted()funciona em qualquer iterável, não apenas em listas. Strings, tuplas, dicionários (você receberá as chaves), geradores, etc., retornando uma lista contendo todos os elementos, classificados.

  • Use list.sort()quando quiser alterar a lista, sorted()quando quiser um novo objeto classificado de volta. Use sorted()quando quiser classificar algo que é iterável, e não uma lista ainda .

  • Para listas, list.sort()é mais rápido do que sorted()porque não precisa criar uma cópia. Para qualquer outro iterável, você não tem escolha.

  • Não, você não pode recuperar as posições originais. Depois que você ligou, list.sort()o pedido original se foi.

Martijn Pieters
fonte
6
Em geral, quando uma função python retorna None, é um sinal de que as operações são feitas no local, por isso, quando você deseja imprimi- list.sort()la, retorna None.
user1767754
45

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.sortquando 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 sortedquando 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 sortedversã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 sorteduma 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 sortedquando necessitasse de uma nova lista ordenada de dados e usaria list.sortquando precisasse ordenar uma lista no local e permitir que isso determinasse meu uso.

Aaron Hall
fonte
4
A configuração do gerador é boa, mas eu não chegaria à conclusão de que você quebrou um mito muito rapidamente. O fato é que ele sorted()precisa alocar um novo objeto de lista e copiar as referências; o restante dos caminhos de código são idênticos. Veja se você pode executar os mesmos testes com listas maiores. Compare-o apenas com a criação de cópias de listas e veja se você consegue replicar as diferenças encontradas, etc.
Martijn Pieters
11

A principal diferença é que sorted(some_list)retorna um novolist :

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

e some_list.sort(), classifica a lista no lugar :

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

Observe que, como a.sort()não retorna nada, print a.sort()será impresso None.


As posições originais de uma lista podem ser recuperadas após list.sort ()?

Não, porque modifica a lista original.

cristão
fonte
1
print a.sort()não imprimirá nada.
Burhan Khalid
1
Será impresso None, vou esclarecer isso.
Christian
1

A função .sort () armazena o valor da nova lista diretamente na variável list; então a resposta para sua terceira pergunta seria NÃO. Além disso, se você fizer isso usando classificado (lista), poderá usá-lo porque não está armazenado na variável de lista. Às vezes, o método .sort () atua como função ou diz que recebe argumentos nele.

Você precisa armazenar o valor de classificado (lista) em uma variável explicitamente.

Também para processamento de dados curtos, a velocidade não terá diferença; mas para listas longas; você deve usar diretamente o método .sort () para um trabalho rápido; mas novamente você enfrentará ações irreversíveis.

Vicrobot
fonte
"A função .sort () armazena o valor da nova lista diretamente na variável da lista" Hein? Que nova lista? Não há nova lista. O list.sort()método classifica o objeto de lista no local.
precisa saber é o seguinte
Além disso, o que isso significa? "às vezes o método .sort () atua como função, ou diz que recebe argumentos nele."
precisa saber é o seguinte
O que quero dizer com nova lista é a lista modificada e .sort () apenas armazena essa lista modificada na mesma variável.
Vicrobot
Sim, às vezes, absolutamente, o .sort()método usa argumentos e atua como função. Também o chamamos de método porque é um atributo do tipo de dados da lista.
precisa saber é o seguinte
Se houver algum tipo de erro no meu conceito, diga-me: procurarei por ele e melhorarei meus conceitos, e também minha resposta. Obrigado
Vicrobot
1

Aqui estão alguns exemplos simples para ver a diferença de ação:

Veja a lista de números aqui:

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

Ao chamar sortedesta lista, sortedfará uma cópia da lista. (Isso significa que sua lista original permanecerá inalterada.)

Vamos ver.

sorted(nums)

retorna

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

Olhando para o numsnovo

nums

Vemos a lista original (inalterada e NÃO classificada). sortednão alterou a lista original

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

Tomando a mesma numslista e aplicando a sortfunção nela, a lista atual será alterada.

Vamos ver.

Começando com nossa numslista para garantir que o conteúdo ainda seja o mesmo.

nums

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

nums.sort()

Agora a lista de números originais foi alterada e, observando os números, vemos que nossa lista original foi alterada e agora está classificada.

nums
[-3, 1, 2, 4, 5, 7, 8, 14]
Stryker
fonte
Obrigado por mostrar o original vs. a cópia com mais profundidade
Brendan Metcalfe
0

Nota: A diferença mais simples entre sort () e classificado () é: sort () não retorna nenhum valor enquanto, classificado () retorna uma lista iterável.

sort () não retorna nenhum valor.

O método sort () apenas classifica os elementos de uma determinada lista em uma ordem específica - Crescente ou Decrescente sem retornar nenhum valor.

A sintaxe do método sort () é:

list.sort(key=..., reverse=...)

Como alternativa, você também pode usar a função incorporada do Python classificada () para a mesma finalidade. função classificada retornar lista classificada

 list=sorted(list, key=..., reverse=...)
Projesh Bhoumik
fonte