web-dev-qa-db-fra.com

filtrer les éléments dans un dictionnaire python où les clés contiennent une chaîne spécifique

Je suis un codeur C qui développe quelque chose en python. Je sais comment faire ce qui suit en C (et donc dans la logique semblable à celle appliquée à Python), mais je me demande quelle est la méthode de "Python" pour le faire.

J'ai un dictionnaire d, et je voudrais opérer sur un sous-ensemble des éléments, seuls ceux dont la clé (chaîne) contient une sous-chaîne spécifique.

c'est-à-dire que la logique C serait:

for key in d:
    if filter_string in key:
        # do something
    else
        # do nothing, continue

J'imagine la version python serait quelque chose comme

filtered_dict = crazy_python_syntax(d, substring)
for key,value in filtered_dict.iteritems():
    # do something

J'ai trouvé beaucoup d'articles sur les dictionnaires de filtrage, mais je ne pouvais pas en trouver un qui impliquait exactement cela.

Mon dictionnaire n'est pas imbriqué et j'utilise python 2.7

76
memo

Que diriez-vous d'un compréhension de dictée :

filtered_dict = {k:v for k,v in d.iteritems() if filter_string in k}

Une fois que vous le voyez, il devrait s’expliquer lui-même, car il se lit très bien comme en anglais.

Cette syntaxe nécessite Python 2.7 ou supérieur.

Dans Python 3, il n’existe que dict.items() , et non iteritems(). Vous devez donc utiliser:

filtered_dict = {k:v for (k,v) in d.items() if filter_string in k}
151

Optez pour ce qui est le plus lisible et facilement maintenable. Ce n'est pas parce que vous pouvez l'écrire en une seule ligne que vous devriez le faire. Votre solution existante est proche de ce que j'utiliserais, sinon que je l'utilisais pour éviter la recherche de valeur, et je déteste les if imbriqués si je peux les éviter:

for key, val in d.iteritems():
    if filter_string not in key:
        continue
    # do something

Cependant, si vous voulez vraiment quelque chose qui vous permette de parcourir le dicté filtré, je ne ferais pas le processus en deux étapes pour le construire puis le parcourir, mais plutôt pour utiliser un générateur, car quoi de plus Pythonic (et génial) que un générateur?

Tout d'abord, nous créons notre générateur, et une bonne conception exige que nous le rendions suffisamment abstrait pour pouvoir être réutilisé:

# The implementation of my generator may look vaguely familiar, no?
def filter_dict(d, filter_string):
    for key, val in d.iteritems():
        if filter_string not in key:
            continue
        yield key, val

Et ensuite, nous pouvons utiliser le générateur pour résoudre votre problème Nice et proprement avec un code simple et compréhensible:

for key, val in filter_dict(d, some_string):
    # do something

En bref: les générateurs sont géniaux.

15
Brendan F
input = {"A":"a", "B":"b", "C":"c"}
output = {k:v for (k,v) in input.items() if key_satifies_condition(k)}
8
jspurim

Jonathon vous a proposé une approche utilisant des interprétations dict dans sa réponse . Voici une approche qui traite de votre partie faire quelque chose .

Si vous voulez faire quelque chose avec les valeurs du dictionnaire, vous n'avez pas du tout besoin de comprendre le dictionnaire:

J'utilise iteritems() puisque vous avez marqué votre question avec python-2.7

results = map(some_function, [(k,v) for k,v in a_dict.iteritems() if 'foo' in k])

Maintenant, le résultat sera dans une liste avec some_function appliqué à chaque paire clé/valeur du dictionnaire, qui a foo dans sa clé.

Si vous voulez juste traiter les valeurs et ignorer les clés, changez simplement la compréhension de la liste:

results = map(some_function, [v for k,v in a_dict.iteritems() if 'foo' in k])

some_function peut être appelable, ainsi un lambda fonctionnerait aussi bien:

results = map(lambda x: x*2, [v for k,v in a_dict.iteritems() if 'foo' in k])

La liste interne n'est en fait pas nécessaire, car vous pouvez passer une expression du générateur à mapper également:

>>> map(lambda a: a[0]*a[1], ((k,v) for k,v in {2:2, 3:2}.iteritems() if k == 2))
[4]
7
Burhan Khalid

Vous pouvez utiliser la fonction de filtrage intégrée pour filtrer les dictionnaires, les listes, etc. en fonction de conditions spécifiques.

filtered_dict = dict(filter(lambda item: filter_str in item[0], d.items()))

L'avantage est que vous pouvez l'utiliser pour différentes structures de données.

6
Pulkit