我是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 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)
感谢每一个建议或暗示,以帮助我理解所有这些背后的逻辑,以便我能够弄明白。
答案 0 :(得分:1)
这是一个简单的解决方案。这个想法只是循环通过dict,进入一个列表,然后从该列表创建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 :(得分:1)
递归确实是解决问题的方法。您可以定义生成器函数,该函数在构造遇到项的路径时递归遍历字典。当您遇到非dict项目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
。
答案 2 :(得分:1)
在所有dicts上嵌套for循环非常简单:
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))
输出你想要的。