Skip to content

Ordinare un elenco di dizionari in base al valore della chiave specifica in Python

Python

In Python, l’ordinamento di un elenco di dizionari con il metodo sort() o la funzione sorted() genera l’errore TypeError per il metodo predefinito.

Specificando il parametro chiave di sort() o sorted(), è possibile ordinare un elenco di dizionari in base al valore della chiave specifica.

In questo articolo vengono descritti i seguenti contenuti.

  • L’ordinamento di un elenco di dizionari generi un errore per un elenco predefinito
  • Specificare le espressioni lambda per il parametro chiave
  • Specificare operator.mgetter() per il parametro chiave
  • Ordina per più chiavi
  • max(), min() per un elenco di dizionari

I codici di esempio seguenti utilizzano un elenco di dizionari con chiavi comuni. Il modulo pprint utilizzatore viene per semplificare la lettura dell’output.

import pprint

l = [{'Name': 'Alice', 'Age': 40, 'Point': 80},
     {'Name': 'Bob', 'Age': 20},
     {'Name': 'Charlie', 'Age': 30, 'Point': 70}]

L’ordinamento di un elenco di dizionari generi un errore per un elenco predefinito

L’ordinamento di un elenco di dizionari (dict) con il metodo sort() o la funzione sorted() generale l’errore TypeError per la direttiva predefinita.

Questo perché il dizionario non supporta i confronti con <, >, ecc.

# sorted(l)
# TypeError: '<' not supported between instances of 'dict' and 'dict'

Specificare le espressioni lambda per il parametro chiave

Per ordinare un elenco di dizionari in base al valore della chiave specifica, specificare il parametro chiave del metodo sort() o della funzione sorted().

Specificando una funzione da applicare a ciascun elemento dell’elenco, viene ordinata in base al risultato di tale funzione. Per ulteriori informazioni, vedere il seguente articolo.

In questo esempio, puoi specificare una funzione per ottenere il valore di una chiave specifica dal dizionario.

È possibile definire una funzione con def, ma in questo caso è conveniente utilizzare espressioni lambda.

pprint.pprint(sorted(l, key=lambda x: x['Age']))
# [{'Age': 20, 'Name': 'Bob'},
#  {'Age': 30, 'Name': 'Charlie', 'Point': 70},
#  {'Age': 40, 'Name': 'Alice', 'Point': 80}]

pprint.pprint(sorted(l, key=lambda x: x['Name']))
# [{'Age': 40, 'Name': 'Alice', 'Point': 80},
#  {'Age': 20, 'Name': 'Bob'},
#  {'Age': 30, 'Name': 'Charlie', 'Point': 70}]

Specificare se ordinare in ordine decrescente o crescente con il parametro reverse.

pprint.pprint(sorted(l, key=lambda x: x['Age'], reverse=True))
# [{'Age': 40, 'Name': 'Alice', 'Point': 80},
#  {'Age': 30, 'Name': 'Charlie', 'Point': 70},
#  {'Age': 20, 'Name': 'Bob'}]

Gli esempi finora utilizzati sorted(), ma puoi specificare key e reverse allo stesso modo con il metodo sort() di list.

Per la differenza tra sort() e sorted(), vedere il seguente articolo. sort() ordina l’oggetto originale stesso e sorted() crea un nuovo oggetto ordinato.

Quando la chiave specificata non esiste

Con il modo mostrato sopra, viene generato un errore se la chiave specificata non esiste.

# sorted(l, key=lambda x: x['Point'])
# KeyError: 'Point'

In tal caso, utilizzare il metodo get() dict, che restituisce il valore predefinito per chiavi inesistenti.

Per configurazione predefinita, get() restituisce Nessuno per chiavi inesistenti. Nessuno non è paragonabile a un numero oa una stringa, quindi viene generato un errore.

# sorted(l, key=lambda x: x.get('Point'))
# TypeError: '<' not supported between instances of 'int' and 'NoneType'

È possibile specificare un valore per una chiave che non esiste come secondo argomento di get(). Gli elementi le cui chiavi non vengono sostituiti con il valore specificato nel secondo argomento e ordinati.

pprint.pprint(sorted(l, key=lambda x: x.get('Point', 75)))
# [{'Age': 30, 'Name': 'Charlie', 'Point': 70},
#  {'Age': 20, 'Name': 'Bob'},
#  {'Age': 40, 'Name': 'Alice', 'Point': 80}]

Infinity inf è determinato come maggiore di qualsiasi altro numero, quindi puoi usare inf e -inf per posizionare sempre elementi senza chiave alla fine o all’inizio.

pprint.pprint(sorted(l, key=lambda x: x.get('Point', float('inf'))))
# [{'Age': 30, 'Name': 'Charlie', 'Point': 70},
#  {'Age': 40, 'Name': 'Alice', 'Point': 80},
#  {'Age': 20, 'Name': 'Bob'}]

pprint.pprint(sorted(l, key=lambda x: x.get('Point', -float('inf'))))
# [{'Age': 20, 'Name': 'Bob'},
#  {'Age': 30, 'Name': 'Charlie', 'Point': 70},
#  {'Age': 40, 'Name': 'Alice', 'Point': 80}]

Specificare operator.mgetter() per il parametro chiave

Puoi anche usare itemgetter() del modulo operatore della libreria standard. È più veloce dell’utilizzo di un’espressione lambda.

import operator

pprint.pprint(sorted(l, key=operator.itemgetter('Age')))
# [{'Age': 20, 'Name': 'Bob'},
#  {'Age': 30, 'Name': 'Charlie', 'Point': 70},
#  {'Age': 40, 'Name': 'Alice', 'Point': 80}]

pprint.pprint(sorted(l, key=operator.itemgetter('Name')))
# [{'Age': 40, 'Name': 'Alice', 'Point': 80},
#  {'Age': 20, 'Name': 'Bob'},
#  {'Age': 30, 'Name': 'Charlie', 'Point': 70}]

Se la chiave specificata non esiste, si verifica un errore.

# sorted(l, key=operator.itemgetter('Point'))
# KeyError: 'Point'

Ordina per più chiavi

Quello che segue è un esempio di un caso in cui i dizionari hanno lo stesso valore per una chiave comune. Due hanno dizionari il valore ‘CA’ per la chiave ‘Stato’.

l_dup = [{'Name': 'Alice', 'Age': 40, 'Point': 80, 'State': 'CA'},
         {'Name': 'Bob', 'Age': 20, 'State': 'NY'},
         {'Name': 'Charlie', 'Age': 30, 'Point': 70, 'State': 'CA'}]

Se i valori sono uguali, l’ordine originale viene mantenuto.

pprint.pprint(sorted(l_dup, key=operator.itemgetter('State')))
# [{'Age': 40, 'Name': 'Alice', 'Point': 80, 'State': 'CA'},
#  {'Age': 30, 'Name': 'Charlie', 'Point': 70, 'State': 'CA'},
#  {'Age': 20, 'Name': 'Bob', 'State': 'NY'}]

È possibile specificare più argomenti per operator.itemgetter() e, se i valori per la prima chiave sono uguali, verranno confrontati e ordinati in base al valore della chiave successiva.

pprint.pprint(sorted(l_dup, key=operator.itemgetter('State', 'Age')))
# [{'Age': 30, 'Name': 'Charlie', 'Point': 70, 'State': 'CA'},
#  {'Age': 40, 'Name': 'Alice', 'Point': 80, 'State': 'CA'},
#  {'Age': 20, 'Name': 'Bob', 'State': 'NY'}]

Si noti che se l’ordine degli argomenti è diverso, anche il risultato è diverso.

pprint.pprint(sorted(l_dup, key=operator.itemgetter('Age', 'State')))
# [{'Age': 20, 'Name': 'Bob', 'State': 'NY'},
#  {'Age': 30, 'Name': 'Charlie', 'Point': 70, 'State': 'CA'},
#  {'Age': 40, 'Name': 'Alice', 'Point': 80, 'State': 'CA'}]

Lo stesso può essere fatto con le espressioni lambda che restituiscono più valori come tuple o elenchi.

pprint.pprint(sorted(l_dup, key=lambda x: (x['State'], x['Age'])))
# [{'Age': 30, 'Name': 'Charlie', 'Point': 70, 'State': 'CA'},
#  {'Age': 40, 'Name': 'Alice', 'Point': 80, 'State': 'CA'},
#  {'Age': 20, 'Name': 'Bob', 'State': 'NY'}]

max(), min() per un elenco di dizionari

Come accennato in precedenza, i confronti con < o > non sono supportati per i dizionari dict, quindi passare un elenco di dizionari a max() o min() provoca un errore.

# max(l)
# TypeError: '>' not supported between instances of 'dict' and 'dict'

Come con sorted() e sort(), puoi anche specificare il parametro chiave in max() e min().

print(max(l, key=lambda x: x['Age']))
# {'Name': 'Alice', 'Age': 40, 'Point': 80}

print(min(l, key=lambda x: x['Age']))
# {'Name': 'Bob', 'Age': 20}

Viene restituito il dizionario dict, quindi se vuoi ottenere un valore, specifica una chiave.

print(max(l, key=lambda x: x['Age'])['Age'])
# 40

Ovviamente puoi anche usare operator.itemgetter().

print(max(l, key=operator.itemgetter('Age')))
# {'Name': 'Alice', 'Age': 40, 'Point': 80}