140 votes

Un moyen efficace de supprimer les clés contenant des chaînes vides d'un dict.

J'ai un dict et je voudrais supprimer toutes les clés pour lesquelles il y a des chaînes de valeurs vides.

metadata = {u'Composite:PreviewImage': u'(Binary data 101973 bytes)',
            u'EXIF:CFAPattern2': u''}

Quelle est la meilleure façon de procéder ?

13voto

Joel Cornett Points 10475

La solution de BrenBarn est idéal (et pythique, j'ajouterais). Voici cependant une autre solution (fp) :

from operator import itemgetter
dict(filter(itemgetter(1), metadata.items()))

8voto

Ryan Points 1718

Si vous avez un dictionnaire imbriqué et que vous voulez que cela fonctionne même pour les sous-éléments vides, vous pouvez utiliser une variante récursive de la suggestion de BrenBarn :

def scrub_dict(d):
    if type(d) is dict:
        return dict((k, scrub_dict(v)) for k, v in d.iteritems() if v and scrub_dict(v))
    else:
        return d

7voto

Hector Oliveros Points 100

Pour python 3

dict((k, v) for k, v in metadata.items() if v)

6voto

dreftymac Points 7843

Réponse rapide (TL;DR)

Exemple01

### example01 -------------------

mydict  =   { "alpha":0,
              "bravo":"0",
              "charlie":"three",
              "delta":[],
              "echo":False,
              "foxy":"False",
              "golf":"",
              "hotel":"   ",                        
            }
newdict =   dict([(vkey, vdata) for vkey, vdata in mydict.iteritems() if(vdata) ])
print newdict

### result01 -------------------
result01 ='''
{'foxy': 'False', 'charlie': 'three', 'bravo': '0'}
'''

Réponse détaillée

Problème

  • Le contexte : Python 2.x
  • Scénario : Le développeur souhaite modifier un dictionnaire pour exclure les valeurs vides
    • aka supprimer les valeurs vides d'un dictionnaire
    • aka supprimer les clés avec des valeurs vides
    • aka dictionnaire de filtre pour les valeurs non vides sur chaque paire clé-valeur

Solución

  • exemple01 : utiliser la syntaxe python de compréhension des listes avec une conditionnelle simple pour supprimer les valeurs " vides ".

Pièges

  • exemple01 n'opère que sur une copie du dictionnaire original (ne modifie pas sur place)
  • L'exemple01 peut produire des résultats inattendus selon ce que le développeur entend par "vide".
    • Est-ce que le développeur veut dire qu'il faut garder les valeurs qui sont falsy ?
    • Si les valeurs du dictionnaire ne sont pas garanties comme étant des chaînes de caractères, le développeur peut avoir des pertes de données inattendues.
    • Le résultat01 montre que seules trois paires clé-valeur ont été préservées de l'ensemble original.

Autre exemple

  • exemple02 permet de faire face aux écueils potentiels
  • L'approche consiste à utiliser une définition plus précise de "vide" en modifiant le conditionnel.
  • Ici, nous voulons seulement filtrer les valeurs qui correspondent à des chaînes vides.
  • Ici, nous utilisons également .strip() pour filtrer les valeurs qui ne sont constituées que d'espaces blancs.

Exemple02

### example02 -------------------

mydict  =   { "alpha":0,
              "bravo":"0",
              "charlie":"three",
              "delta":[],
              "echo":False,
              "foxy":"False",
              "golf":"",
              "hotel":"   ",
            }
newdict =   dict([(vkey, vdata) for vkey, vdata in mydict.iteritems() if(str(vdata).strip()) ])
print newdict

### result02 -------------------
result02 ='''
{'alpha': 0,
  'bravo': '0', 
  'charlie': 'three', 
  'delta': [],
  'echo': False,
  'foxy': 'False'
  }
'''

Voir aussi

5voto

kwinkunks Points 1926

En s'appuyant sur les réponses de patriciasz y nneonneo et en tenant compte du fait que vous pourriez vouloir supprimer des clés qui n'ont que certaines choses fausses (par ex. '' ) mais pas d'autres (par exemple 0 ), ou peut-être même que vous voulez inclure des éléments véridiques (par ex. 'SPAM' ), vous pouvez alors établir une liste de résultats très spécifique :

unwanted = ['', u'', None, False, [], 'SPAM']

Malheureusement, cela ne fonctionne pas tout à fait, car par exemple 0 in unwanted évalue à True . Nous devons faire la distinction entre 0 et d'autres choses peu fiables, nous devons donc utiliser is :

any([0 is i for i in unwanted])

...évalue à False .

Utilisez-le maintenant pour del les choses non désirées :

unwanted_keys = [k for k, v in metadata.items() if any([v is i for i in unwanted])]
for k in unwanted_keys: del metadata[k]

Si vous voulez un nouveau dictionnaire, au lieu de modifier metadata en place :

newdict = {k: v for k, v in metadata.items() if not any([v is i for i in unwanted])}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X