Filtrer les dictionnaires et créer des sous-dictionnaires basés sur des clés / valeurs en Python?

StackOverflow https://stackoverflow.com/questions/1214968

Question

Ok, je suis coincé, j'ai besoin d'aide d'ici ...

Si j'ai un dictionnaire principal comme celui-ci:

data = [ {"key1": "value1", "key2": "value2", "key1": "value3"},  
{"key1": "value4", "key2": "value5", "key1": "value6"}, 
{"key1": "value1", "key2": "value8", "key1": "value9"} ]

Maintenant, je dois déjà consulter ce dictionnaire pour formater certaines données, par exemple:

for datadict in data:  
    for key, value in datadict.items():  
    ...filter the data...

Maintenant, comment pourrais-je d'une manière ou d'une autre dans la même boucle (si possible ... sinon suggérer des alternatives) vérifier les valeurs de certaines clés, et si ces valeurs correspondent à mes préréglages, j'ajouterais cette liste complète à un autre dictionnaire , créant ainsi efficacement des dictionnaires plus petits au fur et à mesure que je sortais de ce dictionnaire principal basé sur certaines clés et valeurs?

Donc, disons que je veux créer un sous-dictionnaire avec toutes les listes dans lesquelles clé1 a la valeur "valeur1", ce qui pour la liste ci-dessus me donnerait quelque chose comme ça:

subdata = [ {"key1": "value1", "key2": "value2", "key1": "value3"},  
{"key1": "value1", "key2": "value8", "key1": "value9"} ]
Était-ce utile?

La solution

Voici une façon pas si jolie de le faire. Le résultat est un générateur, mais si vous voulez vraiment une liste, vous pouvez l'entourer d'un appel à list () . Surtout ce n'est pas grave.

Le prédicat est une fonction qui décide pour chaque paire clé / valeur si un dictionnaire de la liste va la couper. Celui par défaut accepte tout. Si aucune paire k / v dans le dictionnaire ne correspond, elle est rejetée.

def filter_data(data, predicate=lambda k, v: True):
    for d in data:
         for k, v in d.items():
               if predicate(k, v):
                    yield d


test_data = [{"key1":"value1", "key2":"value2"}, {"key1":"blabla"}, {"key1":"value1", "eh":"uh"}]
list(filter_data(test_data, lambda k, v: k == "key1" and v == "value1"))
# [{'key2': 'value2', 'key1': 'value1'}, {'key1': 'value1', 'eh': 'uh'}]

Autres conseils

Net des problèmes déjà soulignés dans d'autres commentaires et réponses (plusieurs clés identiques ne peuvent pas être dans un dict, etc.), voici comment je procéderais:

def select_sublist(list_of_dicts, **kwargs):
    return [d for d in list_of_dicts 
            if all(d.get(k)==kwargs[k] for k in kwargs)]

subdata = select_sublist(data, key1='value1')

La réponse est trop simple, alors je suppose que nous manquons certaines informations. Quoi qu'il en soit:

result = []
for datadict in data:
    for key, value in datadict.items():
        thefiltering()

    if datadict.get('matchkey') == 'matchvalue':
        result.append(datadict)

De plus, vous " dictionnaire principal " n'est pas un dictionnaire mais une liste. Je voulais juste clarifier cela.

Inspiré par la réponse de Skurmedal, je l'ai divisé en un schéma récursif pour utiliser une base de données de dictionnaires imbriqués. Dans ce cas, un " enregistrement " est le sous-dictionnaire du coffre. Le prédicat définit les enregistrements que nous recherchons - ceux qui correspondent à certaines paires (clé, valeur) où ces paires peuvent être profondément imbriquées.

def filter_dict(the_dict, predicate=lambda k, v: True):
    for k, v in the_dict.iteritems():
        if isinstance(v, dict) and _filter_dict_sub(predicate, v):
            yield k, v

def _filter_dict_sub(predicate, the_dict):
    for k, v in the_dict.iteritems():
        if isinstance(v, dict) and filter_dict_sub(predicate, v):
            return True
        if predicate(k, v):
            return True
    return False

S'agissant d'un générateur, vous devrez peut-être encapsuler avec dict (filter_dict (the_dict)) pour obtenir un dictionnaire filtré.

C’est une vieille question, mais pour une raison quelconque, il n’existe pas de réponse de syntaxe à une ligne:

{ k: v for k, v in <SOURCE_DICTIONARY>.iteritems() if <CONDITION> }

Par exemple:

src_dict = { 1: 'a', 2: 'b', 3: 'c', 4: 'd' }
predicate = lambda k, v: k % 2 == 0
filtered_dict = { k: v for k, v in src_dict.iteritems() if predicate(k, v) }

print "Source dictionary:", src_dict
print "Filtered dictionary:", filtered_dict

Produira le résultat suivant:

Source dictionary: {1: 'a', 2: 'b', 3: 'c', 4: 'd'}
Filtered dictionary: {2: 'b', 4: 'd'}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top