Ordinamento una Lista in Python

Una delle operazioni più comuni e ricorrenti che si applicano alle liste è l'ordinamento degli elementi. In particolare, è molto comune ordinare una lista di numeri in ordine crescente o ordine decrescente.

In Python esistono due modi per ordinare una lista:

  1. Usando il metodo sort di una lista;
  2. Usando la funzione sorted di Python.

In questa lezione vedremo come usare entrambi i modi.

Ordinare una lista: metodo sort

Le liste in Python possiedono un metodo molto importante per poter ordinare gli elementi che contengono: il metodo sort.

Di base, il metodo sort ordina gli elementi in ordine crescente. Ad esempio, supponiamo di avere la lista di numeri seguenti:

numeri = [3, 1, 2, 8, 5, 4, 7, 6]

Possiamo usare il metodo sort in questo modo:

numeri.sort()

Dopo aver eseguito questo codice, la lista numeri sarà ordinata in questo modo:

[1, 2, 3, 4, 5, 6, 7, 8]

La prima cosa da notare è che il metodo sort non crea una nuova lista ma ordina la lista esistente. Si tratta quindi di un operazione in-place.

L'ordinamento può essere applicato anche ad altri tipi di dato. Ad esempio possiamo ordinare una lista di stringhe. In tal caso il metodo sort ordinerà la lista in ordine lessicografico. Ad esempio, supponiamo di avere la lista di stringhe seguenti:

nomi = ["Mario", "Luigi", "Peach", "Toad", "Yoshi"]

Possiamo usare il metodo sort in questo modo:

nomi.sort()

Il risultato sarà il seguente:

["Luigi", "Mario", "Peach", "Toad", "Yoshi"]
Nota

Stringhe e Ordinamento Lessicografico

Il metodo sort ordina le stringhe in ordine lessicografico. Questo significa che le stringhe che iniziano con la stessa lettera verranno ordinate in base alla seconda lettera, e così via.

Tuttavia, nel determinare la precedenza tra lettere, le lettere maiuscole e minuscole sono considerate diverse. Ad esempio, la lettera A viene considerata come precedente alla lettera a.

Per cui, una lista di stringhe come la seguente:

nomi = ["Anna", "Alberto", "antonio", "alessandro"]

Sarà ordinata in questo modo:

["Alberto", "Anna", "alessandro", "antonio"]

Quando si usa il metodo sort bisogna, però, fare attenzione a due importanti limitazioni:

  1. Il metodo sort non può essere usato su liste contenenti elementi di tipi diversi. Ad esempio, se si prova ad ordinare una lista contenente sia numeri che stringhe, si otterrà un errore. Supponiamo di avere la lista seguente:

    lista = [1, 2, 3, "quattro", 5]
    

    Se si prova ad ordinare la lista in questo modo:

    lista.sort()
    

    Si otterrà un errore del tipo TypeError:

    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      TypeError: '<' not supported between instances of 'str' and 'int'
    

    Questo errore indica che non è possibile applicare l'operatore di confronto < tra un oggetto di tipo str e un oggetto di tipo int. Quindi arriviamo alla seconda limitazione:

  2. Il metodo sort non può essere usato su liste contenenti elementi di tipi che non supportano l'operatore di confronto <.

    Ad esempio, se proviamo a ordinare una lista contenente due numeri complessi, per cui matematicamente non è possibile effettuare un confronto, otteniamo un errore:

    lista = [1 + 2j, 3 + 4j]
    lista.sort()
    
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      TypeError: '<' not supported between instances of 'complex' and 'complex'
    

Ricapitolando:

Definizione

Metodo sort di una lista

Il metodo sort di una lista ordina gli elementi della lista stessa in ordine crescente. Il metodo sort non può essere usato su liste contenenti elementi di tipi diversi o di tipi che non supportano l'operatore di confronto <. Inoltre, il metodo sort non crea una nuova lista ma ordina la lista esistente.

La sintassi per usarlo è la seguente:

lista.sort()

Ordinamento in ordine decrescente

Il metodo sort ordina gli elementi in ordine crescente. Per ordinare gli elementi in ordine decrescente è possibile usare il parametro opzionale reverse. Questo parametro, di tipo booleano, deve essere impostato a True per ordinare gli elementi in ordine decrescente. Ad esempio, supponiamo di avere la lista di numeri seguenti:

numeri = [3, 1, 2, 8, 5, 4, 7, 6]

Possiamo usare il metodo sort in questo modo:

numeri.sort(reverse=True)

Dopo aver eseguito questo codice, la lista numeri sarà ordinata in questo modo:

[8, 7, 6, 5, 4, 3, 2, 1]

Vediamo un altro esempio in cui vogliamo ordinare in ordine decrescente una lista di stringhe. Supponiamo di avere la lista di stringhe seguenti:

nomi = ["Mario", "Luigi", "Peach", "Toad", "Yoshi"]

Possiamo usare il metodo sort in questo modo:

nomi.sort(reverse=True)

Il risultato sarà il seguente:

["Yoshi", "Toad", "Peach", "Mario", "Luigi"]
Definizione

Ordinamento in ordine decrescente delle liste

Per ordinare gli elementi in ordine decrescente è possibile usare il metodo sort con il parametro opzionale reverse.

La sintassi è:

lista.sort(reverse=True)

Chiave di ordinamento: parametro key

Normalmente, il metodo sort applicato ad una lista prende i valori dei singoli elementi e li confronta con l'operatore < per verificare quale elemento è minore e quale è maggiore. Ad esempio, se si vuole ordinare una lista di numeri, il metodo sort confronta i valori numerici degli elementi. Se si vuole ordinare una lista di stringhe, il metodo sort confronta le stringhe stesse.

Possiamo modificare questo comportamento del metodo sort con il parametro key. Questo parametro deve essere una funzione che viene applicata a ciascun elemento della lista prima di ordinare gli elementi. Quindi, preso in ingresso un valore, tale funzione deve restituire un valore che verrà usato per il confronto.

Per chiarire il tutto, prendiamo un esempio. Supponiamo di avere una lista di numeri in virgola mobile:

numeri = [3.14, -1.41, 2.71, -8.88, -5.55, 4.44, 7.77, -6.66]

Vogliamo ordinare questa lista non in base al valore degli elementi, ma in base al loro valore assoluto. Per far questo possiamo specificare una funzione di questo tipo:

def key_valore_assoluto(x: float):
    return abs(x)

La funzione key_valore_assoluto prende in ingresso un numero in virgola mobile e restituisce il suo valore assoluto. Adesso, possiamo invocare il metodo sort in questo modo:

numeri.sort(key=key_valore_assoluto)

Dopo aver eseguito questo codice, la lista numeri sarà ordinata in questo modo:

[-1.41, 2.71, 3.14, 4.44, -5.55, -6.66, 7.77, -8.88]

Come si può vedere, la lista è stata ordinata in base al valore assoluto degli elementi. In particolare, gli elementi con valore assoluto minore sono stati messi in testa alla lista.

Per brevità, avremmo potuto evitare di definire una nuova funzione e passare direttamente la funzione abs come parametro key:

numeri.sort(key=abs)

Vediamo un altro esempio. Supponiamo di voler ordinare una lista di stringhe indipendentemente dal fatto che contengano lettere maiuscole o minuscole; cioè vogliamo ordinare le stringhe in modo case insensitive. Per farlo, possiamo usare una funzione del genere:

def key_minuscole(x: str):
    # Restituisce la stringa x convertita in minuscolo
    return x.lower()
nomi = ["alberto", "anna", "Antonio", "Alessandra", "andrea"]
nomi.sort(key=key_minuscole)

Dopo aver eseguito questo codice, la lista nomi sarà ordinata in questo modo:

["alberto", "Alessandra", "andrea", "anna", "Antonio"]

Ricapitolando:

Definizione

Parametro key del metodo sort per le liste

Il parametro key del metodo sort permette di specificare una funzione che viene applicata a ciascun elemento della lista prima di ordinare gli elementi. Quindi, preso in ingresso un valore, tale funzione deve restituire un valore che verrà usato per il confronto.

La sintassi è:

lista.sort(key=funzione)

Dove funzione è una funzione che prende in ingresso un solo valore e restituisce un solo valore.

Ordinamento di una lista con la funzione sorted

Il metodo sort che abbiamo visto sopra è un metodo di ordinamento in-place. Questo significa che modifica la lista stessa. Non sempre è possibile o desiderabile modificare la lista che si vuole ordinare, ad esempio nel caso in cui l'ordinamento esistente abbia un significato particolare.

In questi casi è possibile usare la funzione sorted.

La funzione sorted prende in ingresso un iterabile, ossia un oggetto che può essere scorso o attraversato dall'inizio alla fine come una lista, e restituisce una lista ordinata. La lista originale non viene modificata.

Vediamo un esempio. Supponiamo di avere la seguente lista di numeri:

numeri = [3.14, -1.41, 2.71, -8.88, -5.55, 4.44, 7.77, -6.66]

Possiamo ordinare questa lista in modo crescente con la funzione sorted in questo modo:

numeri_ordinati = sorted(numeri)

L'oggetto numeri_ordinati è una nuova lista che contiene gli stessi elementi di numeri ma ordinati in modo crescente:

>>> type(numeri_ordinati)
<class 'list'>
>>> numeri_ordinati
[-8.88, -6.66, -5.55, -1.41, 2.71, 3.14, 4.44, 7.77]

Adesso per poter scorrere gli elementi in ordine crescente possiamo usare un ciclo for:

for numero in numeri_ordinati:
    print(numero)
-8.88
-6.66
-5.55
-1.41
2.71
3.14
4.44
7.77

Come si può vedere, gli elementi sono stati ordinati in modo crescente. Inoltre, la lista originale non è stata toccata, infatti:

print(numeri)
[3.14, -1.41, 2.71, -8.88, -5.55, 4.44, 7.77, -6.66]

La funzione sorted ha, ovviamente, gli stessi limiti del metodo sort, ossia non è possibile applicarla a liste contenenti elementi di tipo diverso.

Inoltre, è possibile ordinare una lista anche in ordine decrescente. Per farlo, possiamo usare il parametro reverse:

for numero in sorted(numeri, reverse=True):
    print(numero)
7.77
4.44
3.14
2.71
-1.41
-5.55
-6.66
-8.88

Infine, anche la funzione sorted permette di specificare una funzione key che viene applicata a ciascun elemento della lista prima di ordinare gli elementi. Per esempio, possiamo ordinare la lista numeri in base al valore assoluto degli elementi, come abbiamo fatto con il metodo sort, in questo modo:

for numero in sorted(numeri, key=abs):
    print(numero)
-1.41
2.71
3.14
4.44
-5.55
-6.66
7.77
-8.88

Ricapitolando:

Definizione

Funzione sorted applicata alle liste

La funzione sorted prende in ingresso una lista e restituisce una nuova lista con gli elementi ordinati in ordine crescente. La sintassi è:

nuova_lista = sorted(lista)

Dove lista è una lista di elementi dello stesso tipo.

La funzione sorted ha due parametri opzionali:

  • reverse: se impostato a True, restituisce una lista con gli elementi ordinati in ordine decrescente. Il valore di default è False.
  • key: se impostato, restituisce una lista con gli elementi ordinati in base al valore restituito dalla funzione key applicata a ciascun elemento della lista di partenza.

La lista originale passata alla funzione sorted non viene modificata.

In Sintesi

In questa lezione abbiamo visto come ordinare una lista in Python usando due modi.

Il primo modo è quello di usare il metodo sort che modifica la lista stessa. Il metodo sort ha due parametri opzionali: reverse e key. Il parametro reverse permette di ordinare la lista in modo decrescente. Il parametro key permette di specificare una funzione che viene applicata a ciascun elemento della lista prima di ordinare gli elementi.

Il secondo modo è quello di usare la funzione sorted che restituisce una nuova lista ordinata in ordine crescente. Anche la funzione sorted ha due parametri opzionali: reverse e key. Questi parametri funzionano allo stesso modo dei parametri reverse e key del metodo sort.

In entrambe i casi è necessario che gli elementi della lista siano dello stesso tipo.

La scelta tra il metodo sort e la funzione sorted dipende dal contesto. Si deve usare sorted quando non si vuole modificare la lista originale.