使用重复键

时间:2016-11-05 23:44:27

标签: python dictionary multidimensional-array

我是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)

感谢每一个建议或暗示,以帮助我理解所有这些背后的逻辑,以便我能够弄明白。

3 个答案:

答案 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))

输出你想要的。