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
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}
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.
input = {"A":"a", "B":"b", "C":"c"}
output = {k:v for (k,v) in input.items() if key_satifies_condition(k)}
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]