Qual'è la differenza tra sorted(list)
vs list.sort()
?
list.sort
muta l'elenco sul posto e restituisce None
sorted
accetta qualsiasi iterabile e restituisce un nuovo elenco, ordinato.
sorted
è equivalente a questa implementazione di Python, ma la funzione integrata di CPython dovrebbe essere misurabile in modo più veloce come è scritto in 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 usare quale?
- Uso
list.sort
quando non si desidera mantenere l'ordine di ordinamento originale (in tal modo sarà possibile riutilizzare l'elenco sul posto in memoria.) E quando si è il solo proprietario dell'elenco (se l'elenco è condiviso da altri codici e si mutalo, potresti introdurre dei bug dove viene usato quell'elenco.)
- Utilizzare
sorted
quando si desidera conservare l'ordinamento originale o quando si desidera creare un nuovo elenco di cui è proprietario solo il codice locale.
Le posizioni originali di un elenco possono essere recuperate dopo list.sort ()?
No - a meno che tu non ne abbia fatto una copia tu stesso, tali informazioni vengono perse perché l'ordinamento viene eseguito sul posto.
"E quale è più veloce? E quanto più veloce?"
Per illustrare la penalità della creazione di un nuovo elenco, utilizzare il modulo timeit, ecco la nostra configurazione:
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
"""
Ed ecco i nostri risultati per un elenco di 10000 numeri interi disposti in modo casuale, come possiamo vedere qui, abbiamo smentito un mito di spesa per la creazione di un elenco precedente :
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]
Dopo alcuni feedback, ho deciso che sarebbe desiderabile un altro test con caratteristiche diverse. Qui fornisco lo stesso elenco ordinato in modo casuale di 100.000 di lunghezza per ogni iterazione 1.000 volte.
import timeit
setup = """
import random
random.seed(0)
lst = list(range(100000))
random.shuffle(lst)
"""
Interpreto la differenza di questo tipo più grande proveniente dalla copia menzionata da Martijn, ma non domina al punto dichiarato nella risposta più popolare più vecchia qui, qui l'aumento del tempo è solo di circa il 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]
Ho anche eseguito quanto sopra su un ordinamento molto più piccolo e ho visto che la nuova sorted
versione della copia richiede ancora circa il 2% di tempo di esecuzione in più su una sorta di lunghezza 1000.
Anche Poke eseguiva il proprio codice, ecco il codice:
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))
Ha trovato un ordinamento di lunghezza di 1000000, (eseguito 100 volte) un risultato simile, ma solo un aumento del 5% circa nel tempo, ecco l'output:
10000000 100
l = next(it); l.sort()
610.5015971539542
l = next(it); sorted(l)
646.7786222379655
Conclusione:
Un elenco di grandi dimensioni che viene ordinato con la sorted
creazione di una copia probabilmente dominerà le differenze, ma l'ordinamento stesso domina l'operazione e organizzare il codice attorno a queste differenze sarebbe un'ottimizzazione prematura. Vorrei utilizzare sorted
quando ho bisogno di un nuovo elenco ordinato dei dati, e vorrei utilizzare list.sort
quando ho bisogno di ordinare un elenco sul posto e lasciare che questo determini il mio utilizzo.
sorted()
chiedi (per sbaglio) un argomento di stringa ma pensi che sia un elenco, ottieni un risultato di elenco, non una stringa : nonsorted("abcd", reverse=True)
dà['d', 'c', 'b', 'a']
"dcba"