Qual è la differenza tra `ordinati (elenco)` vs `list.sort ()`?


194

list.sort()ordina l'elenco e sostituisce l'elenco originale, mentre sorted(list)restituisce una copia ordinata dell'elenco, senza modificare l'elenco originale.

  • Quando uno è preferito rispetto all'altro?
  • Qual è più efficiente? Di quanto?
  • È possibile ripristinare un elenco allo stato non ordinato dopo che list.sort()è stato eseguito?

4
Fai attenzione se sorted()chiedi (per sbaglio) un argomento di stringa ma pensi che sia un elenco, ottieni un risultato di elenco, non una stringa : non sorted("abcd", reverse=True)['d', 'c', 'b', 'a']"dcba"
smci

Risposte:


317

sorted()restituisce un nuovo elenco ordinato, lasciando inalterato l'elenco originale. list.sort()ordina l'elenco sul posto , mutando gli indici dell'elenco e restituisce None(come tutte le operazioni sul posto).

sorted()funziona su qualsiasi iterabile, non solo su elenchi. Stringhe, tuple, dizionari (otterrai le chiavi), generatori, ecc., Che restituiscono un elenco contenente tutti gli elementi, ordinati.

  • Utilizzare list.sort()quando si desidera modificare l'elenco, sorted()quando si desidera ripristinare un nuovo oggetto ordinato. Utilizzare sorted()quando si desidera ordinare qualcosa che è iterabile, non ancora un elenco .

  • Per gli elenchi, list.sort()è più veloce di sorted()perché non è necessario crearne una copia. Per ogni altro iterabile, non hai scelta.

  • No, non è possibile recuperare le posizioni originali. Una volta chiamato list.sort()l'ordine originale è sparito.


6
In generale, quando viene restituita una funzione Python None, è un segno che le operazioni sono eseguite sul posto, ecco perché, quando si desidera stampare list.sort(), restituisce None.
user1767754

45

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 sortedquando 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 sortedversione 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 sortedcreazione 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 sortedquando ho bisogno di un nuovo elenco ordinato dei dati, e vorrei utilizzare list.sortquando ho bisogno di ordinare un elenco sul posto e lasciare che questo determini il mio utilizzo.


4
La configurazione del generatore è buona, ma non trarrei la conclusione che hai rotto un mito troppo in fretta. Resta il fatto che sorted()deve allocare un nuovo oggetto elenco e copiare i riferimenti; il resto dei percorsi del codice sono identici. Vedi se riesci a eseguire gli stessi test con elenchi più grandi. Confrontalo con la semplice creazione di copie degli elenchi e vedi se riesci a replicare le differenze che hai trovato, ecc.
Martijn Pieters

11

La differenza principale è che sorted(some_list)restituisce un nuovolist :

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

e some_list.sort(), ordina l'elenco in atto :

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

Si noti che poiché a.sort()non restituisce nulla, print a.sort()verrà stampato None.


È possibile recuperare un elenco di posizioni originali dopo list.sort ()?

No, perché modifica l'elenco originale.


1
print a.sort()non stampa nulla.
Burhan Khalid,

1
Stamperà None, lo chiarirò.
Christian

1

La funzione .sort () memorizza il valore della nuova lista direttamente nella variabile lista; quindi la risposta per la tua terza domanda sarebbe NO. Inoltre, se lo fai usando l'ordinamento (elenco), puoi ottenerlo perché non è memorizzato nella variabile elenco. Inoltre a volte il metodo .sort () funge da funzione, o dice che accetta argomenti al suo interno.

Devi memorizzare il valore di ordinato (elenco) in una variabile in modo esplicito.

Anche per l'elaborazione di dati brevi la velocità non avrà alcuna differenza; ma per lunghi elenchi; dovresti usare direttamente il metodo .sort () per un lavoro veloce; ma ancora una volta dovrai affrontare azioni irreversibili.


"La funzione .sort () memorizza il valore della nuova lista direttamente nella variabile lista" Eh? Quale nuovo elenco? Non c'è un nuovo elenco. Il list.sort()metodo ordina l'oggetto elenco sul posto.
PM 2Ring

Inoltre, cosa dovrebbe significare questo? "a volte il metodo .sort () funge da funzione o dice che accetta argomenti al suo interno."
PM 2Ring

Ciò che intendo per nuovo elenco è l'elenco modificato e .sort () memorizza solo l'elenco modificato nella stessa variabile.
Vicrobot,

Sì, assolutamente talvolta il .sort()metodo prende argomento e agisce come funzione. Inoltre lo chiamiamo metodo perché è un attributo del tipo di dati elenco.
Vicrobot,

Se c'è una sorta di errore nel mio concetto, dimmelo, lo cercherò e migliorerò i miei concetti e anche la mia risposta. Grazie
Vicrobot il

1

Ecco alcuni semplici esempi per vedere la differenza nell'azione:

Vedi l'elenco dei numeri qui:

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

Quando si chiama sortedquesto elenco, sortedverrà creata una copia dell'elenco. (Significa che l'elenco originale rimarrà invariato.)

Vediamo.

sorted(nums)

ritorna

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

Guardando di numsnuovo

nums

Vediamo l'elenco originale (inalterato e NON ordinato.). sortednon ha modificato l'elenco originale

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

Prendendo lo stesso numselenco e applicando la sortfunzione su di esso, cambierà l'elenco effettivo.

Vediamo.

A partire dal nostro numselenco per essere sicuri, il contenuto è sempre lo stesso.

nums

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

nums.sort()

Ora l'elenco dei numeri originali è cambiato e guardando i numeri vediamo che il nostro elenco originale è cambiato e ora è ordinato.

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

Grazie per aver mostrato l'originale contro la copia in modo più approfondito
Brendan Metcalfe,

0

Nota: la differenza più semplice tra sort () e sort () è: sort () non restituisce alcun valore mentre, sort () restituisce un elenco iterabile.

sort () non restituisce alcun valore.

Il metodo sort () ordina semplicemente gli elementi di un determinato elenco in un ordine specifico - Ascendente o Discendente senza restituire alcun valore.

La sintassi del metodo sort () è:

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

In alternativa, puoi anche usare la funzione integrata di Python ordinata () per lo stesso scopo. funzione ordinata restituisce l'elenco ordinato

 list=sorted(list, key=..., reverse=...)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.