2016-11-05 72 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

非常感谢你的帮助,代码不正是我在找什么。我非常感谢你的贡献,它帮助了很多! –