Comment créer des dicts imbriqués en Python?

j'ai 2 fichiers csv. La première est un fichier de données et un autre fichier de mappage. Fichier de mappage a 4 colonnes Device_Name GDN Device_Type Device_OS Ce sont également les colonnes qui sont présentes dans le fichier de données et doivent être travaillées sur.

Le fichier de données

contient des données dont la colonne Device_Name est remplie et les 3 autres colonnes sont vides. Le fichier de mappage contient toutes les colonnes peuplées. Je veux que mon code Python ouvre les deux fichiers et que pour chaque nom de périphérique dans le fichier de données, sa valeur GDN, Device_Type & Device_OS fichier de mappage.

je sais utiliser dict quand seulement 2 colonnes sont présentes (1 est nécessaire pour être mappé) mais je ne sais pas comment l'accomplir quand 3 colonnes doivent être mappées.

ci-dessous est le code en utilisant lequel j'ai essayé d'accomplir la cartographie de Device_Type :

x = dict([])
with open("Pricing Mapping_2013-04-22.csv", "rb") as in_file1:
    file_map = csv.reader(in_file1, delimiter=',')
    for row in file_map:
       typemap = [row[0],row[2]]
       x.append(typemap)

with open("Pricing_Updated_Cleaned.csv", "rb") as in_file2, open("Data Scraper_GDN.csv", "wb") as out_file:
    writer = csv.writer(out_file, delimiter=',')
    for row in csv.reader(in_file2, delimiter=','):
         try:
              row[27] = x[row[11]]
         except KeyError:
              row[27] = ""
         writer.writerow(row)

il renvoie le Atribute Error .

après quelques recherches, j'ai réalisé que j'avais besoin de créer un dict imbriqué, mais je n'en ai pas idée sur la façon de le faire. Aidez-moi à trouver une solution ou poussez-moi dans la bonne direction.

95
demandé sur gsamaras 2013-05-02 12:14:40

4 réponses

imbriquée dict est un dictionnaire dans un dictionnaire. Une chose très simple.

>>> d = {}
>>> d['dict1'] = {}
>>> d['dict1']['innerkey'] = 'value'
>>> d
{'dict1': {'innerkey': 'value'}}

vous pouvez également utiliser un defaultdict du paquet collections pour faciliter la création de dictionnaires imbriqués.

>>> import collections
>>> d = collections.defaultdict(dict)
>>> d['dict1']['innerkey'] = 'value'
>>> d  # currently a defaultdict type
defaultdict(<type 'dict'>, {'dict1': {'innerkey': 'value'}})
>>> dict(d)  # but is exactly like a normal dictionary.
{'dict1': {'innerkey': 'value'}}

vous pouvez peupler cela comme vous voulez.

je recommande dans votre code quelque chose comme le suivant:

d = {}  # can use defaultdict(dict) instead

for row in file_map:
    # derive row key from something 
    # when using defaultdict, we can skip the next step creating a dictionary on row_key
    d[row_key] = {} 
    for idx, col in enumerate(row):
        d[row_key][idx] = col

selon votre commentaire :

est peut-être au-dessus du code, ce qui prête à confusion. Mon problème en bref: j' avoir 2 fichiers A. csv B. csv, A. csv has 4 columns I j k l,B. csv a également ces colonnes. je est une sorte de colonnes de clé pour ces csvs'. colonne J k L est vide en a. csv mais peuplé en B. csv. Je veux cartographier les valeurs de J k l des colonnes en utilisant "i"comme colonne clé de B. csv à A. fichier csv

Ma suggestion serait quelque chose de comme c' (sans l'aide de defaultdict):

a_file = "path/to/a.csv"
b_file = "path/to/b.csv"

# read from file a.csv
with open(a_file) as f:
    # skip headers
    f.next()
    # get first colum as keys
    keys = (line.split(',')[0] for line in f) 

# create empty dictionary:
d = {}

# read from file b.csv
with open(b_file) as f:
    # gather headers except first key header
    headers = f.next().split(',')[1:]
    # iterate lines
    for line in f:
        # gather the colums
        cols = line.strip().split(',')
        # check to make sure this key should be mapped.
        if cols[0] not in keys:
            continue
        # add key to dict
        d[cols[0]] = dict(
            # inner keys are the header names, values are columns
            (headers[idx], v) for idx, v in enumerate(cols[1:]))

s'il vous plaît noter que, pour l'analyse des fichiers csv il ya un module csv .

196
répondu Inbar Rose 2017-05-23 12:26:35

UPDATE : pour une longueur arbitraire d'un dictionnaire emboîté, allez à this answer .

utilisez la fonction defaultdict des collections.

Haute performance: "si la clé pas dans les dict" est très coûteux lorsque l'ensemble de données est grand.

faible maintenance: rend le code plus lisible et peut être facilement étendu.

from collections import defaultdict

target_dict = defaultdict(dict)
target_dict[key1][key2] = val
49
répondu Junchen 2017-06-05 02:09:43

Pour des niveaux arbitraires de nestedness:

In [2]: def nested_dict():
   ...:     return collections.defaultdict(nested_dict)
   ...:

In [3]: a = nested_dict()

In [4]: a
Out[4]: defaultdict(<function __main__.nested_dict>, {})

In [5]: a['a']['b']['c'] = 1

In [6]: a
Out[6]:
defaultdict(<function __main__.nested_dict>,
            {'a': defaultdict(<function __main__.nested_dict>,
                         {'b': defaultdict(<function __main__.nested_dict>,
                                      {'c': 1})})})
15
répondu andrew 2016-03-30 04:18:32

il est important de se rappeler lors de l'utilisation de defaultdict et de modules similaires de dict imbriqués tels que nested_dict, que la recherche d'une clé inexistante peut créer par inadvertance une nouvelle entrée de clé dans le dict et causer beaucoup de dégâts. Voici un exemple de Python3 avec nested_dict.

import nested_dict as nd
nest = nd.nested_dict()
nest['outer1']['inner1'] = 'v11'
nest['outer1']['inner2'] = 'v12'
print('original nested dict: \n', nest)
try:
    nest['outer1']['wrong_key1']
except KeyError as e:
    print('exception missing key', e)
print('nested dict after lookup with missing key.  no exception raised:\n', nest)

# instead convert back to normal dict
nest_d = nest.to_dict(nest)
try:
    print('converted to normal dict. Trying to lookup Wrong_key2')
    nest_d['outer1']['wrong_key2']
except KeyError as e:
    print('exception missing key', e)
else:
    print(' no exception raised:\n')
# or use dict.keys to check if key in nested dict.
print('checking with dict.keys')
print(list(nest['outer1'].keys()))
if 'wrong_key3' in list(nest.keys()):

    print('found wrong_key3')
else:
    print(' did not find wrong_key3')

sortie:

original nested dict:   {"outer1": {"inner2": "v12", "inner1": "v11"}}

nested dict after lookup with missing key.  no exception raised:  
{"outer1": {"wrong_key1": {}, "inner2": "v12", "inner1": "v11"}} 

converted to normal dict. 
Trying to lookup Wrong_key2 

exception missing key 'wrong_key2' 

checking with dict.keys 

['wrong_key1', 'inner2', 'inner1']  
did not find wrong_key3
0
répondu Skysail 2017-03-03 21:04:08