J'ai un dict
qui a tout un tas d'entrées. Je ne suis intéressé que par quelques-uns d'entre eux. Existe-t-il un moyen facile de tailler tous les autres?
J'ai un dict
qui a tout un tas d'entrées. Je ne suis intéressé que par quelques-uns d'entre eux. Existe-t-il un moyen facile de tailler tous les autres?
Réponses:
Construire un nouveau dict:
dict_you_want = { your_key: old_dict[your_key] for your_key in your_keys }
Utilise la compréhension du dictionnaire.
Si vous utilisez une version qui en manque (c'est-à-dire Python 2.6 et versions antérieures), faites-la dict((your_key, old_dict[your_key]) for ...)
. C'est la même chose, mais plus laid.
Notez que cela, contrairement à la version de jnnnnn, a des performances stables (ne dépend que du nombre de your_keys) pour les old_dict
s de n'importe quelle taille. Tant en termes de vitesse que de mémoire. Comme il s'agit d'une expression de générateur, elle traite un élément à la fois et ne passe pas en revue tous les éléments de old_dict.
Suppression de tout en place:
unwanted = set(keys) - set(your_dict)
for unwanted_key in unwanted: del your_dict[unwanted_key]
old_dict
indique un bogue ailleurs, et dans ce cas, je préfère de loin une erreur à des résultats silencieusement erronés.
Compréhension du dict un peu plus élégante:
foodict = {k: v for k, v in mydict.items() if k.startswith('foo')}
mydict.iteritems()
place. .items()
crée une autre liste.
Voici un exemple en python 2.6:
>>> a = {1:1, 2:2, 3:3}
>>> dict((key,value) for key, value in a.iteritems() if key == 1)
{1: 1}
La partie filtrage est l' if
instruction.
Cette méthode est plus lente que la réponse de Delnan si vous ne souhaitez sélectionner que quelques-unes des très nombreuses clés.
if key in ('x','y','z')
je suppose.
Vous pouvez le faire avec la fonction de projet de ma bibliothèque funcy :
from funcy import project
small_dict = project(big_dict, keys)
Jetez également un œil à select_keys .
Code 1:
dict = { key: key * 10 for key in range(0, 100) }
d1 = {}
for key, value in dict.items():
if key % 2 == 0:
d1[key] = value
Code 2:
dict = { key: key * 10 for key in range(0, 100) }
d2 = {key: value for key, value in dict.items() if key % 2 == 0}
Code 3:
dict = { key: key * 10 for key in range(0, 100) }
d3 = { key: dict[key] for key in dict.keys() if key % 2 == 0}
Toutes les performances de code assemblées sont mesurées avec timeit en utilisant nombre = 1000, et collectées 1000 fois pour chaque morceau de code.
Pour python 3.6, les performances de trois façons de filtrer les touches dict sont presque les mêmes. Pour python 2.7, le code 3 est légèrement plus rapide.
Ce liner lambda devrait fonctionner:
dictfilt = lambda x, y: dict([ (i,x[i]) for i in x if i in set(y) ])
Voici un exemple:
my_dict = {"a":1,"b":2,"c":3,"d":4}
wanted_keys = ("c","d")
# run it
In [10]: dictfilt(my_dict, wanted_keys)
Out[10]: {'c': 3, 'd': 4}
Il s'agit d'une compréhension de base de la liste itérant sur vos clés dict (i en x) et génère une liste de paires de tuple (clé, valeur) si la clé réside dans la liste de clés souhaitée (y). Un dict () encapsule le tout pour produire un objet dict.
set
pour wanted_keys
, mais sinon, il semble bon.
dictfilt({'x':['wefwef',52],'y':['iuefiuef','efefij'],'z':['oiejf','iejf']}, ('x','z'))
:, il revient {'x': ['wefwef', 52], 'z': ['oiejf', 'iejf']}
comme prévu.
dict={'0':[1,3], '1':[0,2,4], '2':[1,4]}
et le résultat a été {}
, que j'ai supposé être un dict blanc.
foo = {'0':[1,3], '1':[0,2,4], '2':[1,4]}; dictfilt(foo,('0','2'))
:, j'obtiens: {'0': [1, 3], '2': [1, 4]}
quel est le résultat escompté
Compte tenu de votre dictionnaire d'origine orig
et de l'ensemble des entrées qui vous intéressent keys
:
filtered = dict(zip(keys, [orig[k] for k in keys]))
ce qui n'est pas aussi agréable que la réponse de delnan, mais devrait fonctionner dans toutes les versions de Python d'intérêt. Il est cependant fragile pour chaque élément keys
existant dans votre dictionnaire d'origine.
Sur la base de la réponse acceptée par delnan.
Que faire si l'une de vos clés recherchées n'est pas dans l'ancien_dict? La solution delnan lèvera une exception KeyError que vous pouvez intercepter. Si ce n'est pas ce dont vous avez besoin, vous voudrez peut-être:
n'inclut que les clés qui s'exécutent à la fois dans l'ancien_dict et dans votre jeu de clés recherchées.
old_dict = {'name':"Foobar", 'baz':42}
wanted_keys = ['name', 'age']
new_dict = {k: old_dict[k] for k in set(wanted_keys) & set(old_dict.keys())}
>>> new_dict
{'name': 'Foobar'}
ont une valeur par défaut pour les clés qui n'est pas définie dans old_dict.
default = None
new_dict = {k: old_dict[k] if k in old_dict else default for k in wanted_keys}
>>> new_dict
{'age': None, 'name': 'Foobar'}
{k: old_dict.get(k, default) for k in ...}
Cette fonction fera l'affaire:
def include_keys(dictionary, keys):
"""Filters a dict by only including certain keys."""
key_set = set(keys) & set(dictionary.keys())
return {key: dictionary[key] for key in key_set}
Tout comme la version de delnan, celle-ci utilise la compréhension du dictionnaire et a des performances stables pour les grands dictionnaires (dépendant uniquement du nombre de clés que vous autorisez, et non du nombre total de clés dans le dictionnaire).
Et tout comme la version de MyGGan, celle-ci permet à votre liste de clés d'inclure des clés qui peuvent ne pas exister dans le dictionnaire.
Et en bonus, voici l'inverse, où vous pouvez créer un dictionnaire en excluant certaines clés dans l'original:
def exclude_keys(dictionary, keys):
"""Filters a dict by excluding certain keys."""
key_set = set(dictionary.keys()) - set(keys)
return {key: dictionary[key] for key in key_set}
Notez que contrairement à la version de delnan, l'opération n'est pas effectuée sur place, donc les performances sont liées au nombre de clés dans le dictionnaire. Cependant, l'avantage de ceci est que la fonction ne modifiera pas le dictionnaire fourni.
Modifier: Ajout d'une fonction distincte pour exclure certaines touches d'un dict.
invert
signifie que l' keys
argument est conservé ou que l' keys
argument est rejeté?", Combien d'entre elles seraient d'accord?
Si nous voulons créer un nouveau dictionnaire avec les clés sélectionnées supprimées, nous pouvons utiliser la compréhension du dictionnaire
Par exemple:
d = {
'a' : 1,
'b' : 2,
'c' : 3
}
x = {key:d[key] for key in d.keys() - {'c', 'e'}} # Python 3
y = {key:d[key] for key in set(d.keys()) - {'c', 'e'}} # Python 2.*
# x is {'a': 1, 'b': 2}
# y is {'a': 1, 'b': 2}
Une autre option:
content = dict(k1='foo', k2='nope', k3='bar')
selection = ['k1', 'k3']
filtered = filter(lambda i: i[0] in selection, content.items())
Mais vous obtenez un list
(Python 2) ou un itérateur (Python 3) retourné par filter()
, pas un dict
.
filtered
dans dict
et vous revenez le dictionnaire!
Voici une autre méthode simple à utiliser del
dans une doublure:
for key in e_keys: del your_dict[key]
e_keys
est la liste des clés à exclure. Il mettra à jour votre dict plutôt que de vous en donner un nouveau.
Si vous voulez un nouveau dict de sortie, faites une copie du dict avant de le supprimer:
new_dict = your_dict.copy() #Making copy of dict
for key in e_keys: del new_dict[key]
Vous pourriez utiliser python-benedict
, c'est une sous-classe dict.
Installation: pip install python-benedict
from benedict import benedict
dict_you_want = benedict(your_dict).subset(keys=['firstname', 'lastname', 'email'])
C'est open-source sur GitHub: https://github.com/fabiocaccamo/python-benedict
Avertissement: je suis l'auteur de cette bibliothèque.