web-dev-qa-db-fra.com

Grouper et agréger une liste de dictionnaires par plusieurs clés

J'ai une liste comprenant des dictionnaires (List[Dict, Dict, ...]), Je voudrais unifier la liste sur la base de deux clés, mais je souhaite conserver la valeur d'une autre clé dans le dictionnaire pour m'assurer de ne pas la perdre en créant une liste dans la clé que je souhaite conserver. J'utilise Python pour le code. Si cela a une importance Python 3.x pour être exact.

Supposons que j'ai la liste de dictionnaires suivante avec trois clés: number, favorite et color. Je veux unifier les éléments de la liste à l'aide des touches number et favorite. Cependant pour les dictionnaires qui ont les mêmes valeurs number et favorite, je voudrais ajouter une liste sous la clé color pour m'assurer d'avoir tous les colors pour la même combinaison de number et favorite. Cette liste doit également être unique car elle ne devrait pas avoir besoin des colors répétés pour la même combinaison. Cependant, s'il n'y a qu'un seul élément pour la couleur de clé dans le résultat final, il doit s'agir d'une chaîne et non d'une liste.

lst = [
{'number': 1, 'favorite': False, 'color': 'red'},
{'number': 1, 'favorite': False, 'color': 'green'},
{'number': 1, 'favorite': False, 'color': 'red'},
{'number': 1, 'favorite': True, 'color': 'red'},
{'number': 2, 'favorite': False, 'color': 'red'}]

En utilisant l'uniqify susmentionné, j'obtiendrais le résultat suivant:

lst = [
    {'number': 1, 'favorite': False, 'color': {'red', 'green'}},
    {'number': 1, 'favorite': True, 'color': 'red'},
    {'number': 2, 'favorite': False, 'color': 'red'},
]

Notez qu'il n'y a qu'une seule instance de rednumber est 1 et favorite est False même s'il est apparu deux fois dans la liste avant d'être uniqifié. Notez également que lorsqu'il n'y a qu'un seul élément pour la clé color dans le deuxième dict, c'est une chaîne et non une liste.

15
KaanTheGuru

Voici une façon de le faire,

J'ai construit un dict en utilisant d'abord un Tuple comme clé composite, puis j'ai créé une nouvelle liste à partir de ce dict. Vous pouvez écrire des compréhensions pour réduire davantage les lignes et l'optimiser, j'espère que cela aide.

new_dict = {}

for item in lst:
    try: # if already exists then append to the list
        new_dict.get((item['number'], item['favorite']))
        new_dict[(item['number'], item['favorite'])].append(item['color'])
    except KeyError: # if it doesn't then create a new entry to that key
        new_dict[(item['number'], item['favorite'])] = [item['color']]


final_list = []
for k, v in new_dict.items(): # keep appending dicts to our list
    final_list.append({'number': k[0], 'favorite': k[1], 'color':set(v)})

print(final_list)

Les sorties:

[{'number': 1, 'favorite': False, 'color': {'green', 'red'}}, {'number': 1, 'favorite': True, 'color': {'red'}}, {'number': 2, 'favorite': False, 'color': {'red'}}]
0
Vineeth Sai

Un de mes amis a créé la fonction suivante pour résoudre ce problème, sans utiliser de bibliothèques externes:

def uniqifyColors(l):
    for elem in l:
        for item in l:
            if elem['number'] == item['number'] and elem['favorite'] == item['favorite']:
                for clr in item['color']:
                    if clr not in elem['color']:
                        elem['color'].append(clr)
    return l

Après avoir utilisé cette fonction Python, il a simplement fait une uniqify triviale pour obtenir les résultats uniques de la liste. Cependant, il ne conserve pas une seule couleur comme chaîne, mais plutôt une liste avec un élément unique.

0
KaanTheGuru