簡體   English   中英

如何將嵌套字典的內容以某種格式寫入文件?

[英]How do I write the contents of nested dictionaries to a file in a certain format?

我有一本字典,我試圖以某種方式輸出其中的信息,以便它可用於下游分析。 注意: dict中的所有鍵也在list

for item in list:
    for key, value in dict[item].items():
        print item, key, value

這是我最接近我想要的,但還有很長的路要走。 理想情況下,我想要的是:

     item1  item2  item3  item4
key1 value  value  value  value
key2 value  value  value  value
key2 value  value  value  value

這甚至可能嗎?

首先,如果我理解你的結構,列表只是為外部字典排序鍵的一種方式,你的很多復雜性是試圖將這兩個一起使用來模擬有序字典。 如果是這樣,有一個更簡單的方法來做到這一點:使用collections.OrderedDict 我會在最后回到那個。


首先,您需要獲取子詞典的所有鍵,因為這些是輸出的行。

從評論中,聽起來dct中的所有子詞典都具有相同的鍵,因此您可以從其中任意一個中取出鍵:

keys = dct.values()[0].keys()

如果每個子字典可以有不同的鍵子集,您需要先通過dct來獲取所有鍵:

keys = reduce(set.union, map(set, dct.values()))

有些人發現reduce難以理解,即使您真的只是將它用作“使用不同運算符sum ”。 對於他們來說,這里是如何明確地做同樣的事情:

keys = set()
for subdct in dct.values():
    keys |= set(subdct)

現在,對於每個鍵的行,我們需要為每個子字典(即外部字典中的每個值)獲取一列,按照使用列表元素作為外部字典的鍵指定的順序。

因此,對於每一列item ,我們要獲取item key 對應的外字典值,然后在生成的子字典中,獲取該行key對應的值。 這在英語中很難說,但在 Python 中,它只是:

dct[item][key]

如果您實際上在所有子詞典中都沒有所有相同的鍵,那么它只是稍微復雜一點:

dct[item].get(key, '')

所以,如果你不想要任何標題,它看起來像這樣:

with open('output.csv', 'wb') as f:
    w = csv.writer(f, delimiter='\t')
    for key in keys:
        w.writerow(dct[item].get(key, '') for item in lst)

要添加標題列,只需將標題(在本例中為key )添加到每一行:

with open('output.csv', 'wb') as f:
    w = csv.writer(f, delimiter='\t')
    for key in keys:
        w.writerow([key], [dct[item].get(key, '') for item in lst])

請注意,我將 genexp 轉換為列表推導式,因此我可以使用列表連接來添加key 從概念上講,將其保留為迭代器並在前面加上itertools.chain更清晰,但在像這樣帶有微小迭代器的微不足道的情況下,我認為這只會使代碼更難閱讀:

with open('output.csv', 'wb') as f:
    w = csv.writer(f, delimiter='\t')
    for key in keys:
        w.writerow(chain([key], (dct[item].get(key, '') for item in lst)))

您還需要一個標題行。 那更容易; 它只是列表中的項目,標題列前面有一個空白列:

with open('output.csv', 'wb') as f:
    w = csv.writer(f, delimiter='\t')
    w.writerow([''] + lst)
    for key in keys:
        w.writerow([key] + [dct[item].get(key, '') for item in lst])

但是,有兩種方法可以使事情變得更簡單。

首先,您可以使用OrderedDict ,因此您不需要單獨的鍵列表。 如果您堅持使用單獨的listdict ,您仍然可以動態構建OrderedDict以使您的代碼更易於閱讀。 例如:

od = collections.OrderedDict((item, dct[item]) for item in lst)

現在:

with open('output.csv', 'wb') as f:
    w = csv.writer(f, delimiter='\t')
    w.writerow([''] + od.keys())
    for key in keys:
        w.writerow([key] + [subdct.get(key, '') for subdct in od.values()])

其次,您可以構建轉置結構:

transposed = {key_b: {key_a: dct[key_a].get(key_b, '') for key_a in dct} 
              for key_b in keys}

然后以明顯的順序對其進行迭代(或使用DictWriter為您處理列的排序,並使用其writerows方法處理行,因此整個事情變成了單行)。

要在 Python 中存儲對象以便以后可以重用它們,您可以使用shelve模塊。 這是一個模塊,可讓您將對象寫入架子文件並重新打開它並稍后檢索對象,但它依賴於操作系統,因此如果說您在 Mac 上制作它並且以后要打開它,它將無法工作它在 Windows 機器上。

import shelve

shelf = shelve.open("filename", flag='c') 
#with flag='c', you have to delete the old shelf if you want to overwrite it

dict1 = #something
dict2 = #something

shelf['key1'] = dict1
shelf['key2'] = dict2

shelf.close()

要從架子上讀取對象:

shelf_reader = shelve.open("filename", flag='r')
for k in shelf_reader.keys():
    retrieved = shelf_reader[k]
    print(retrieved) #prints the retrieved dictionary

shelf_reader.close()

這可能是一個見仁見智的問題,但我認為序列化(嵌套)字典的最佳(也是迄今為止最簡單的)方法之一是使用 JSON 格式:

{ "key1" : { "subkey1" : "value1",
             "subkey2" : "value2" },
  "key2" : {"subkey3" : "value3"} }

最好的是,這可以使用內置的json模塊在一行中完成(用於編碼您的值或解碼它們)!

讓我們考慮您的字典是dico變量:

import json
save_file = open('save_file', 'w')
save_file.write( json.dumps(dico) )

等等 :-) !

如果保證將數據加載回 Python,我建議只使用pickle而不是擔心格式。 如果要將其加載到另一種標准語言中,請考慮改用json - 大多數語言都有用於解析 JSON 格式數據的庫。

也就是說,如果你真的需要發明你自己的格式,你可以做這樣的事情來以 CSV 格式存儲來自所有子字典的所有鍵:

import csv
dict_keys = sorted(dict.keys())
with open("output.csv", "wb") as csvfile:
    writer = csv.writer(csvfile)
    writer.writerow(["Key"] + dict_keys)
    all_keys = reduce(set.union, (set(d) for d in dict.values()))
    for key in sorted(all_keys):
        writer.writerow([key] + [dict[k].get(key, "") for k in dict_keys])

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM