2016-11-05 103 views
3

我是新來的Python和目前使用python 2. 我建了一個多維的字典,看起來像這樣:打印多維字典,重複鍵

targets = {house: {N: {red: {A:1}, garden: {N: 6}}} 
      {great: {A: {very: {Adv:12}, so: {Adv: 5}, a: {Det: 3}}}} 
etc. 

基本上總會有4的嵌套字典,但的條目'第三'字典({red:{},horse:{}等)可以由任意數量的項目組成。因此,字典中的項目數量會有所不同。

現在,我喜歡將字典寫入文件,最好寫入一個csv文件。輸出文件應以製表符分隔的方式顯示所有條目,每行以最外鍵開始。例如:

house N red  A 1 
house N garden N 6 
great A very  Adv 12 
great A so  Adv 5 
great A a  Det 3 

我知道,有很多關於打印多維字典的帖子,但我還沒有找到一個(還),其中最外層的關鍵是在每個迭代中打印。我試圖包含爲多維詞典的其他問題提供的代碼片段,但迄今爲止效果不佳。

我好不容易纔寫字典到字典中的格式正常的.txt文件與此for循環:

for target in targets_dict: 
    results.write(str(target) + str(targets_dict[str(target)]) + '\n') 

或使用csvwriter寫入到一個CSV文件(我知道也有DictWriter,我只是無法得到它的正常工作):

w = csv.writer(results, delimiter = '\t') 
for target in targets_dict.iteritems(): 
    w.writerow(target) 

很顯然,這是非常基本的和迭代不進入內字典。

嘗試已發佈到相關問題的修改解決方案recursively traverse multidimensional dictionary, dimension unknown始終駐留在'期望的字符緩衝區對象'錯誤中。

for for k,v in sorted(targets_dict.items(),key=lambda x: x[0]): 
    if isinstance(v, dict): 
     results.write(" ") + ("%s %s") % (k, v) 

每一個建議或提示都被讚賞,可以幫助我理解所有這些背後的邏輯,以便我能夠弄明白。

+1

回覆。變量'targets':這是一個列表的列表,還是最外面的字典中唯一的關鍵字? – Eugene

+0

都在最外面的字典中的鍵唯一 –

回答

1

這是一個簡單的解決方案。這個想法只是將字典循環到列表中,然後從該列表中創建tsv文件,但僅僅是因爲你知道嵌套深度(4,看起來好)。下面沒有針對速度進行優化,也沒有檢查任何地方的存在,但希望您能明白。

import csv 
targets = {'house': {'N': {'red': {'A':1}, 'garden': {'N': 6}}}, 
      'great': {'A': {'very': {'Adv':12}, 'so': {'Adv': 5}, 'a': {'Det': 3}}}} 
with open('targets.tsv', 'w', newline='\n') as tsvfile: 
    writer = csv.writer(tsvfile, delimiter='\t') 
    for t in targets: 
     for u in targets[t]: 
      for v in targets[t][u]: 
       for w in targets[t][u][v]: 
        #print [t, u, v, w, targets[t][u][v][w]] 
        writer.writerow([t, u, v, w, targets[t][u][v][w]]) 

打印:

['house', 'N', 'red', 'A', 1] 
['house', 'N', 'garden', 'N', 6] 
['great', 'A', 'very', 'Adv', 12] 
['great', 'A', 'so', 'Adv', 5] 
['great', 'A', 'a', 'Det', 3] 

而且還創建了TSV文件:

house N red A 1 
house N garden N 6 
great A very Adv 12 
great A so Adv 5 
great A a Det 3 

編輯:根據在OP(評論在最外面的字典中的鍵唯一更新的代碼並應被視爲targets的關鍵字)。

+1

哇,謝謝你們的努力,遺憾的響應晚。正如我在上面的評論中所說的,目標是最外面的字典,但是我知道你的代碼,它可以幫助我理解整體邏輯。 –

+0

感謝回答並選擇一個答案,讓許多新用戶不這樣做,這是你這樣的人誰恢復我願意幫助那些在SO開始了!再次感謝! – Eugene

+0

更新代碼以反映完成評論。 – Eugene

1

遞歸確實是解決問題的方法。您可以定義遞歸遍歷字典的生成器函數,同時構造遇到的項目的路徑。當您遇到非字典的項目只是yield任何已添加到路徑和寫入到CSV文件:

import csv 

targets = { 
    'house': {'N': {'red': {'A':1}, 'garden': {'N': 6}}}, 
    'great': {'A': {'very': {'Adv':12}, 'so': {'Adv': 5}, 'a': {'Det': 3}}} 
} 

def get_rows(o, path=None): 
    if path is None: 
     path = [] 

    # Base case, add object to path and yield it 
    if not isinstance(o, dict): 
     path.append(o) 
     yield path 
     path.pop() 
     return 

    for k, v in o.items(): 
     path.append(k) 
     yield from get_rows(v, path) 
     path.pop() 

with open('result.csv', 'w', newline='') as f: 
    writer = csv.writer(f, delimiter='\t') 
    for row in get_rows(targets): 
     writer.writerow(row) 

輸出:

great A a Det 3 
great A so Adv 5 
great A very Adv 12 
house N red A 1 
house N garden N 6 

請注意,您得到的輸出可能會以不同的順序因爲dict是無序的。上述解決方案可以與任何深度的嵌套字典一起工作。如果你正在使用Python 2的代碼需要進行調整了一下因爲Python 2沒有yield from

+0

OP狀態「輸出文件應該顯示在一個製表符分隔的方式的所有條目」,需要設置標籤定界符在上面的代碼。 – Eugene

+0

@Eugene好點,解決了。 – niemmi

+0

@niemmi太感謝你了,我使用Python 2這個項目,但我與Python 3試了一下,它提供了所需的輸出,這是完美的,當然;) –

1

這是剛剛巢很簡單的在所有類型的字典循環:

import csv 

targets = {'house': {'N': {'red': {'A':1}, 'garden': {'N': 6}}}, 'great': {'A': {'very': {'Adv':12}, 'so': {'Adv': 5}, 'a': {'Det': 3}}}} 

with open('file.csv', 'wb') as csvfile: 
    csvwriter = csv.writer(csvfile, delimiter='\t') 
    for k,v in targets.iteritems(): 
    for k2,v2 in v.iteritems(): 
     for k3,v3 in v2.iteritems(): 
     for k4,v4 in v3.iteritems(): 
      csvwriter.writerow([str(k), str(k2), str(k3), str(k4), str(v4)]) 
      #print(str(k) + "\t" + str(k2) + "\t" + str(k3) + "\t" + str(k4) + "\t" + str(v4)) 

輸出正是你想要的。

+0

非常感謝你的幫助,代碼不正是我在找什麼。我非常感謝你的貢獻,它幫助了很多! –