Je veux d'abord trier une liste par valeur, puis par deuxième valeur. Y a-t-il un moyen facile de faire ceci? Voici un petit exemple:
A = [{'name':'john','age':45},
{'name':'andi','age':23},
{'name':'john','age':22},
{'name':'paul','age':35},
{'name':'john','age':21}]
Cette commande permet de trier cette liste par 'name'
:
sorted(A, key = lambda user: user['name'])
Mais comment puis-je trier cette liste par une deuxième valeur? Comme 'age'
dans cet exemple.
Je veux un tri comme celui-ci (premier tri par 'name'
puis trier par 'age'
):
andi - 23
john - 21
john - 22
john - 45
paul - 35
Merci!
>>> A = [{'name':'john','age':45},
{'name':'andi','age':23},
{'name':'john','age':22},
{'name':'paul','age':35},
{'name':'john','age':21}]
>>> sorted(A, key = lambda user: (user['name'], user['age']))
[{'age': 23, 'name': 'andi'}, {'age': 21, 'name': 'john'}, {'age': 22, 'name': 'john'}, {'age': 45, 'name': 'john'}, {'age': 35, 'name': 'paul'}]
Cela trie par un tuple des deux attributs, ce qui suit est équivalent et beaucoup plus rapide/plus propre:
>>> from operator import itemgetter
>>> sorted(A, key=itemgetter('name', 'age'))
[{'age': 23, 'name': 'andi'}, {'age': 21, 'name': 'john'}, {'age': 22, 'name': 'john'}, {'age': 45, 'name': 'john'}, {'age': 35, 'name': 'paul'}]
D'après les commentaires: @Bakuriu
Je parie qu'il n'y a pas de grande différence entre les deux, mais
itemgetter
évite un peu de surcharge car il extrait les clés et fait leTuple
pendant un seul opcode (CALL_FUNCTION
), tout en appelant lelambda
devra appeler la fonction, charger les différentes constantes (qui sont d'autres bytecodes) enfin appeler l'indice (BINARY_SUBSCR
), construisez leTuple
et retournez-le ... c'est beaucoup plus de travail pour l'interpréteur.
Pour résumer: itemgetter
maintient l'exécution entièrement au niveau C
, donc c'est aussi rapide que possible.
from operator import itemgetter
sorted(your_list, key=itemgetter('name', 'age'))
Voici la solution générale alternative - elle trie les éléments de dict par clés et valeurs. L'avantage - pas besoin de spécifier de clés, et cela fonctionnerait toujours si certaines clés manquaient dans certains dictionnaires.
def sort_key_func(item):
""" helper function used to sort list of dicts
:param item: dict
:return: sorted list of tuples (k, v)
"""
pairs = []
for k, v in item.items():
pairs.append((k, v))
return sorted(pairs)