Jak utworzyć zagnieżdżony dict w Pythonie?

Mam 2 pliki csv. Pierwszy to plik danych, a drugi to plik mapowania. Plik mapowania ma 4 kolumny Device_Name GDN Device_Type Device_OS Są to również kolumny, które są obecne w pliku danych i trzeba pracować na.

Plik danych zawiera dane z kolumną Device_Name wypełnioną i pozostającymi 3 kolumnami pustymi. Plik mapowania zawiera wszystkie kolumny wypełnione. Chcę, aby mój kod Pythona otwierał oba pliki i dla każdej nazwy urządzenia w pliku danych mapował jego wartość GDN, Device_Type & Device_OS z pliku mapowania.

Wiem jak używać dict, gdy są tylko 2 kolumny (1 jest potrzebne do zmapowania) , ale nie wiem, jak to zrobić, gdy trzeba zmapować 3 kolumny.

Poniżej znajduje się kod, za pomocą którego próbowałem wykonać odwzorowanie 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)

Zwraca Atribute Error.

Po kilku badaniach zdałem sobie sprawę, że muszę stworzyć zagnieżdżony dict, ale nie mam pojęcia, jak to zrobić. Proszę, pomóż mi rozwiązać ten problem lub popchnij mnie we właściwym kierunku, aby rozwiązać ten problem.

Author: gsamaras, 2013-05-02

4 answers

Zagnieżdżony dict jest słownikiem w słowniku. Bardzo prosta rzecz.

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

Możesz również użyć defaultdict z collections pakiet ułatwiający tworzenie zagnieżdżonych słowników.

>>> 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'}}

Możesz wypełnić to, jak chcesz.

Polecam w Twoim kodzie coś Jak :

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

Zgodnie z Twoim komentarz :

Może być powyżej kodu jest mylące pytanie. My problem w skrócie: I mieć 2 pliki a. csv b. csv, a. csv ma 4 kolumny i j k l, b. csv ma również te kolumny. i jest rodzajem kluczowych kolumn dla tych CSV'ów. kolumna j k l jest puste w formacie a.csv, ale wypełnione w formacie B. csv. Chcę mapować wartości j k l columns using ' i ' as key column from b. csv to a. csv file

Moja sugestia byłaby czymś Jak this (bez użycia 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:]))

Należy jednak pamiętać, że do parsowania plików csv jest csv moduł .

 196
Author: Inbar Rose,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:35

UPDATE : aby uzyskać dowolną długość zagnieżdżonego słownika, przejdź do tej odpowiedzi .

Użyj funkcji defaultdict ze zbiorów.

Wysoka wydajność: "jeśli klucz nie jest w dict" jest bardzo drogi, gdy zestaw danych jest duży.

Niskie koszty utrzymania: spraw, aby Kod był bardziej czytelny i można go łatwo rozszerzyć.

from collections import defaultdict

target_dict = defaultdict(dict)
target_dict[key1][key2] = val
 49
Author: Junchen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-05 02:09:43

Dla dowolnych poziomów zagnieżdżenia:

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
Author: andrew,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-30 04:18:32

Ważne jest, aby pamiętać podczas używania defaultdict i podobnych zagnieżdżonych modułów dict, takich jak nested_dict, że wyszukanie nieistniejącego klucza może nieumyślnie spowodować nowy wpis klucza w dict i spowodować wiele spustoszeń. Oto przykład Python3 z 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')

Wyjście To:

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
Author: Skysail,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-03 21:04:08