J'ai créé la logique ci-dessous pour ajouter une liste à un dictionnaire en Python cela fonctionne bien

>>> dict ={}
>>> dict ={"key":[]}
>>> dict['key']
[]
>>> dict['key'].append('a')
>>> dict['key']
['a']

Lorsque j'essaie d'implémenter la même chose tout en analysant le JSON et en créant un dictionnaire dynamique basé sur la certitude qu'il n'a pas réussi à ajouter dans la liste et à signaler comme NoneType

import json
json_data="""{
   "data":[
      {
         "package_path":"/bin/bash",
         "package_type":"rpm"
      },
      {
         "package_path":"com.test3",
         "package_type":"java"
      },
      {
         "package_path":"com.test",
         "package_type":"java"
      }
   ]
}
"""

j_dict = json.loads(json_data)

dict2 = {}
for vuln in j_dict['data']:
   package_type = vuln['package_type']
   package_path = vuln['package_path']

   if package_type in dict2:
      dict2 ={package_type:[]}
   else:
      dict2[package_type].append(package_path)

Lance une erreur

 % python ~/Desktop/test.py
Traceback (most recent call last):
  File "test.py", line 30, in <module>
    dict2[package_type].append(package_path)
KeyError: u'rpm'

Attendre une sortie comme

dict2 {"java":['com.test3','com.test2'],"rpm":['/bin/bash']}

2
anish 2 nov. 2020 à 18:06

3 réponses

Meilleure réponse

Vous pouvez utiliser dict.setdefault pour créer une liste vide si la clé n'est pas trouvée dans le dictionnaire. Par exemple:

import json
json_data="""{
   "data":[
      {
         "package_path":"/bin/bash",
         "package_type":"rpm"
      },
      {
         "package_path":"com.test3",
         "package_type":"java"
      },
      {
         "package_path":"com.test",
         "package_type":"java"
      }
   ]
}
"""

j_dict = json.loads(json_data)
out = {}
for vuln in j_dict['data']:
    out.setdefault(vuln['package_type'], []).append(vuln['package_path'])

print(out)

Tirages:

{'rpm': ['/bin/bash'], 'java': ['com.test3', 'com.test']}
2
Andrej Kesely 2 nov. 2020 à 15:09

defaultdict peut être utilisé ici.

import json
from collections import defaultdict

json_data = """{
   "data":[
      {
         "package_path":"/bin/bash",
         "package_type":"rpm"
      },
      {
         "package_path":"com.test3",
         "package_type":"java"
      },
      {
         "package_path":"com.test",
         "package_type":"java"
      }
   ]
}
"""

j_dict = json.loads(json_data)
data = defaultdict(list)
for entry in j_dict['data']:
    data[entry['package_type']].append(entry['package_path'])
print(data)

Production

defaultdict(<class 'list'>, {'rpm': ['/bin/bash'], 'java': ['com.test3', 'com.test']})
2
balderman 2 nov. 2020 à 15:16

Votre déclaration if est légèrement erronée:

if package_type in dict2:
   dict2 ={package_type:[]}
else:
   dict2[package_type].append(package_path)

Devrait être:

if package_type not in dict2:
   dict2[package_type] = []

dict2[package_type].append(package_path)

Vous disiez, si une clé était dans le dictionnaire, remplacez tout le dictionnaire par une seule clé et une liste comme valeur.

Dans la clause else que vous disiez, si la clé n'existe pas, récupérez la valeur de cette clé, supposez que c'est une liste et ajoutez-y. Ce qui échoue.

Cette expression consistant soit à ajouter de la valeur si elle n'existe pas, soit à utiliser la valeur existante est si courante qu'il existe plusieurs façons différentes de le faire, intégrées à python et à ses bibliothèques.

dict.setdefault définira une nouvelle valeur par défaut pour une clé ou renverra la valeur existante si elle existe. Je trouve sa syntaxe d'appel moche:

dict2.setdefault(package_type, []).append(package_path)

Cela définit la valeur de la clé sur [] si elle n'existe pas, la renvoie, puis vous pouvez l'ajouter à la liste telle qu'elle existe dans le dictionnaire.

Une alternative que je préfère est d'utiliser collections.defaultdict , qui est un dictionnaire qui crée automatiquement une valeur par défaut lorsqu'une clé n'existe pas déjà:

dict2 = defaultdict(list)

dict2[package_type].append(package_path)
1
Peter Wood 2 nov. 2020 à 15:47