2640 votes

Comment trier une liste de dictionnaires par une valeur du dictionnaire ?

Comment trier une liste de dictionnaires par la valeur d'une clé spécifique ? Étant donné :

[{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}]

Lorsqu'ils sont triés par name il devrait devenir :

[{'name':'Bart', 'age':10}, {'name':'Homer', 'age':39}]

6 votes

Lire la réponse et continuer à regarder opérateur.itemgetter . Puis-je trier sur plusieurs valeurs dans le même processus (par exemple nous avons [{'name':'Bart', 'age':10, 'note':3},{'name':'Homer','age':10,'note':2},{'name':'Vasile‌​','age':20,'note':3}‌​] Et à utiliser : from operator import itemgetter newlist = sorted(old_list, key=itemgetter(-'note','name') EDIT : Testé, et ça marche mais je ne sais pas comment faire pour que la note soit DESC et le nom ASC.

20voto

uingtea Points 763

Parfois, nous devons utiliser lower() . Par exemple,

lists = [{'name':'Homer', 'age':39},
  {'name':'Bart', 'age':10},
  {'name':'abby', 'age':9}]

lists = sorted(lists, key=lambda k: k['name'])
print(lists)
# [{'name':'Bart', 'age':10}, {'name':'Homer', 'age':39}, {'name':'abby', 'age':9}]

lists = sorted(lists, key=lambda k: k['name'].lower())
print(lists)
# [ {'name':'abby', 'age':9}, {'name':'Bart', 'age':10}, {'name':'Homer', 'age':39}]

0 votes

Por qué devons-nous utiliser lower() dans ce cas ?

1 votes

La raison la plus probable pour laquelle il faut utiliser lower() ici serait de fournir un tri alphabétique insensible à la casse. Cet exemple d'ensemble de données a une minuscule a avec abby et un B majuscule avec Bart Les exemples montrent donc les résultats sans, puis avec, le tri insensible à la casse par l'intermédiaire de la fonction .lower() .

18voto

abby sobh Points 1464

Utilisation de la Pandas est une autre méthode, bien que son temps d'exécution à grande échelle soit beaucoup plus lent que les méthodes plus traditionnelles proposées par d'autres :

import pandas as pd

listOfDicts = [{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}]
df = pd.DataFrame(listOfDicts)
df = df.sort_values('name')
sorted_listOfDicts = df.T.to_dict().values()

Voici quelques valeurs de référence pour une liste minuscule et une grande liste (100k+) de dicts :

setup_large = "listOfDicts = [];\
[listOfDicts.extend(({'name':'Homer', 'age':39}, {'name':'Bart', 'age':10})) for _ in range(50000)];\
from operator import itemgetter;import pandas as pd;\
df = pd.DataFrame(listOfDicts);"

setup_small = "listOfDicts = [];\
listOfDicts.extend(({'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}));\
from operator import itemgetter;import pandas as pd;\
df = pd.DataFrame(listOfDicts);"

method1 = "newlist = sorted(listOfDicts, key=lambda k: k['name'])"
method2 = "newlist = sorted(listOfDicts, key=itemgetter('name')) "
method3 = "df = df.sort_values('name');\
sorted_listOfDicts = df.T.to_dict().values()"

import timeit
t = timeit.Timer(method1, setup_small)
print('Small Method LC: ' + str(t.timeit(100)))
t = timeit.Timer(method2, setup_small)
print('Small Method LC2: ' + str(t.timeit(100)))
t = timeit.Timer(method3, setup_small)
print('Small Method Pandas: ' + str(t.timeit(100)))

t = timeit.Timer(method1, setup_large)
print('Large Method LC: ' + str(t.timeit(100)))
t = timeit.Timer(method2, setup_large)
print('Large Method LC2: ' + str(t.timeit(100)))
t = timeit.Timer(method3, setup_large)
print('Large Method Pandas: ' + str(t.timeit(1)))

#Small Method LC: 0.000163078308105
#Small Method LC2: 0.000134944915771
#Small Method Pandas: 0.0712950229645
#Large Method LC: 0.0321750640869
#Large Method LC2: 0.0206089019775
#Large Method Pandas: 5.81405615807

4 votes

J'ai exécuté votre code et j'ai trouvé une erreur dans les arguments de timeit.Timer pour les Pandas à méthode large : vous spécifiez "setup_small" alors que ce devrait être "setup_large". En changeant cet argument, le programme s'exécute sans se terminer, et je l'ai arrêté après plus de 5 minutes. Lorsque je l'ai exécuté avec "timeit(1)", les Pandas de la méthode Large se sont terminés en 7,3 secondes, bien pire que LC ou LC2.

0 votes

Vous avez tout à fait raison, c'était un oubli de ma part. Je ne le recommande plus pour les gros cas ! J'ai édité la réponse pour simplement l'autoriser comme une possibilité, le cas d'utilisation est encore à débattre.

16voto

vvladymyrov Points 1765

Voici la solution alternative générale - elle trie les éléments d'un dict par clés et valeurs.

L'avantage de cette méthode est qu'il n'est pas nécessaire de spécifier les clés, et qu'elle fonctionne toujours si certaines clés sont manquantes 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)
sorted(A, key=sort_key_func)

0 votes

Que voulez-vous dire par "trie les éléments d'un dict par clés et valeurs" ? De quelle manière s'effectue le tri ? D'où viennent les valeurs ?

13voto

Srisaila Points 1850

Si vous n'avez pas besoin de l'original list de dictionaries vous pouvez le modifier en place avec sort() en utilisant une fonction de touche personnalisée.

Fonction clé :

def get_name(d):
    """ Return the value of a key in a dictionary. """

    return d["name"]

El list à trier :

data_one = [{'name': 'Homer', 'age': 39}, {'name': 'Bart', 'age': 10}]

Le trier sur place :

data_one.sort(key=get_name)

Si vous avez besoin de l'original list appelez le sorted() en lui passant la fonction list et la fonction clé, puis affecter le tri retourné list à une nouvelle variable :

data_two = [{'name': 'Homer', 'age': 39}, {'name': 'Bart', 'age': 10}]
new_data = sorted(data_two, key=get_name)

Impression data_one y new_data .

>>> print(data_one)
[{'name': 'Bart', 'age': 10}, {'name': 'Homer', 'age': 39}]
>>> print(new_data)
[{'name': 'Bart', 'age': 10}, {'name': 'Homer', 'age': 39}]

12voto

Disons que j'ai un dictionnaire D avec les éléments ci-dessous. Pour trier, il suffit d'utiliser l'argument clé dans sorted pour passer une fonction personnalisée comme ci-dessous :

D = {'eggs': 3, 'ham': 1, 'spam': 2}
def get_count(tuple):
    return tuple[1]

sorted(D.items(), key = get_count, reverse=True)
# Or
sorted(D.items(), key = lambda x: x[1], reverse=True)  # Avoiding get_count function call

Vérifiez este dehors.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X