La funzione Sort () di python è garantita per essere stabile?


95

La documentazione non lo garantisce. C'è qualche altro luogo in cui è documentato?

Immagino che potrebbe essere stabile poiché il metodo di ordinamento sulle liste è garantito per essere stabile (Note 9 ° punto: "A partire da Python 2.3, il metodo sort () è garantito per essere stabile"), e ordinato è funzionalmente simile. Tuttavia, non sono in grado di trovare alcuna fonte definitiva che lo dica.

Scopo: devo ordinare in base a una chiave primaria e anche a una chiave secondaria nei casi in cui la chiave primaria è uguale in entrambi i record. Se sort () è garantito per essere stabile, posso ordinare sulla chiave secondaria, quindi ordinare sulla chiave primaria e ottenere il risultato di cui ho bisogno.

PS: Per evitare qualsiasi confusione, sto usando stable nel senso di "un ordinamento è stabile se garantisce di non cambiare l'ordine relativo degli elementi che si confrontano uguali".

Risposte:


126

Sì, l'intento del manuale è proprio quello di garantire che sortedsia stabile e anzi che utilizzi esattamente lo stesso algoritmo del sortmetodo. Mi rendo conto che i documenti non sono chiari al 100% su questa identità; le patch doc sono sempre accettate con gioia!


2
Ho scoperto che se ordino tuple o elenchi, ogni volta che le chiavi di ordinamento "primarie" sono uguali, finisce per ordinare in base alla chiave "secondaria". Ad esempio, sorted([(1, 2), (1, 1)])restituisce [(1, 1), (1, 2)]invece di restituire l'input originale nella stessa sequenza / ordine. La garanzia di stabilità non dovrebbe significare che dovrebbe restituire l' [(1, 2), (1, 1)]input originale ? In tal caso, devi essere esplicito e diresorted([(1, 2), (1, 1)], key=lambda t: t[0])
code_dredd

10
Non è questo ciò che ci si aspetta in questo caso? Python confronterà le tuple attraverso tutti gli elementi per impostazione predefinita, non solo il primo "primario". Se vuoi ordinare solo il primo elemento, puoi passare il keyparametro in modo esplicito.
Matias Grioni

2
@code_dredd questo è il comportamento previsto. Il punto dell'ordinamento stabile è l'ordinamento utilizzando una "chiave di ordinamento", ma due elementi diversi che hanno la stessa chiave di ordinamento saranno nello stesso ordine. La chiave di ordinamento predefinita per una tupla è costituita da tutti gli elementi della tupla.
guyarad

27

Sono stabili .

A proposito: a volte puoi ignorare se l'ordinamento e l'ordinamento sono stabili, combinando un ordinamento multi-passaggio in uno a passaggio singolo.

Ad esempio, se si desidera ordinare gli oggetti in base alle loro last_name, first_nameattributi, si può fare in un solo passaggio:

sorted_list= sorted(
    your_sequence_of_items,
    key= lambda item: (item.last_name, item.first_name))

sfruttando il confronto delle tuple.

Questa risposta, così com'è, copre la domanda originale. Per ulteriori domande relative all'ordinamento, c'è il Python Sorting How-To .


4
Ciò può avere effetti indesiderati se si desidera invertire l'ordinamento. Ad esempio, quando si ordina in base ai prodotti, è possibile ordinare prima in base alla valutazione (ordine crescente) e poi al prezzo (anche in ordine crescente). Se si inverte questa impostazione, si desidera ordinare in base alla valutazione in ordine decrescente ma in base al prezzo in ordine crescente. Questo non funziona con questa soluzione.
Remco Wendt

2
@ RemcoWendt: non era necessario ciò che descrivi. In ogni caso, considera key= lambda item: (-item.rating, item.price)o fornisci un cmpinvece di un keyargomento. Tuttavia, non sono ancora sicuro dello scopo del tuo commento.
tzot

1
In effetti non era un requisito, ma volevo sottolineare questa sottile differenza quando altre persone lo leggono e fanno una scelta tra la tua soluzione o utilizzando la funzione di ordinamento stabile di Python.
Remco Wendt

Vedo. In altre parole, l'ordinamento per coppie è più chiaro ed è quindi preferibile, a meno che non ti interessi delle prestazioni. Immagino che due ordinamenti stabili siano un po 'più veloci di un ordinamento a coppie, sebbene la differenza possa essere trascurabile -?
Sergey Orshanskiy

8
@tzot Voglio menzionare, ci sono sempre tali requisiti per l'ordinamento stabile. Ad esempio, ho un elenco di tuple (tasso, commento), i commenti vengono salvati nell'ordine in cui sono stati creati e voglio ordinare in base alla frequenza e mantenere l'ordine temporale, tuttavia, non ho salvato il timestamp nell'elenco. Per dirlo brevemente, voglio solo ordinare l'elenco in base alla tariffa e mantenere il commento nello stesso ordine.
wsysuper

3

La documentazione nel frattempo modificata ( commit pertinente ) e l'attuale documentazione di sortedgarantisce esplicitamente:

La sorted()funzione integrata è garantita per essere stabile. Un ordinamento è stabile se garantisce di non modificare l'ordine relativo degli elementi che si confrontano allo stesso modo - questo è utile per l'ordinamento in più passaggi (ad esempio, ordina per dipartimento, quindi per grado di stipendio).

Questa parte della documentazione è stata aggiunta a Python 2.7 e Python 3.4 (+), quindi qualsiasi implementazione conforme di quella versione del linguaggio dovrebbe avere una versione stabile sorted.

Si noti che per CPython list.sortè stato stabile da Python 2.3

  • Tim Peters ha riscritto la sua list.sort()implementazione: questa è un "ordinamento stabile" (input uguali appaiono nello stesso ordine nell'output) e più velocemente di prima.

Non ne sono sicuro al 100% sorted, oggigiorno è semplice da usare list.sort, ma non ho controllato la cronologia per questo. Ma è probabile che sia "sempre" utilizzato list.sort.


0

I documenti "Novità" per Python 2.4 dimostrano efficacemente che sort () prima crea un elenco, quindi chiama sort () su di esso, fornendo la garanzia di cui hai bisogno anche se non nei documenti "ufficiali". Potresti anche controllare la fonte, se sei davvero preoccupato.


1
Potresti indicare dove dice così? Dice sort () "funziona come list.sort ()" e "viene ordinata una copia appena formata", ma non vedo che dica che utilizza internamente sort ().
domenica - Ripristina Monica il

La "copia" che si forma è una lista (che è ciò che ottieni come valore di ritorno), e .sort () viene chiamata su quella lista prima di ritornare. QED. No, non è una prova inattaccabile, ma finché Python non avrà uno standard ufficiale non lo otterrai.
Peter Hansen

0

Il documento Python 3.6 sull'ordinamento ora lo afferma

Gli ordinamenti sono garantiti per essere stabili

Inoltre, in quel documento, c'è un collegamento alla stabile Timsort , che lo afferma

Timsort è stato l'algoritmo di ordinamento standard di Python dalla versione 2.3

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.