【问题标题】:print multidimensional dictionary with repeating key使用重复键打印多维字典
【发布时间】:2017-03-19 13:48:37
【问题描述】:

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

我知道,有很多关于打印多维字典的帖子,但是我还没有找到一个(还)在每次迭代期间打印最外面的键的帖子。我尝试包含为有关多维词典的其他问题提供的代码 sn-ps,但到目前为止效果不佳。

我只是设法用这个 for 循环将字典写入字典格式的普通 .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)

感谢每一个建议或提示,以帮助我理解这一切背后的逻辑,以便我能够弄清楚。

【问题讨论】:

  • 回复。变量targets:这是一个字典列表,还是最外层字典中的所有键都是唯一的?
  • 最外层字典中的所有键都是唯一的

标签: python dictionary multidimensional-array


【解决方案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

EDIT:根据 OP 中的注释更新代码(最外层字典中的键是唯一的,应视为 targets 的键)。

【讨论】:

  • 哇,感谢您的努力,很抱歉回复晚了。正如我在上面的评论中所说,目标是最外层的字典,但是我了解您的代码,它有助于我理解整体逻辑。
  • 感谢您回复和选择答案,很多新用户都没有这样做,正是像您这样的人恢复了我帮助那些刚开始使用 SO 的人的意愿!再次感谢!
【解决方案2】:

在所有字典上嵌套 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))

输出你想要的。

【讨论】:

  • 非常感谢您的帮助,代码完全符合我的要求。非常感谢您的贡献,它帮助很大!
【解决方案3】:

递归确实是解决问题的方法。您可以定义生成器函数,该函数在构造遇到项目的路径时递归遍历字典。当您遇到非字典项目时,只需 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

【讨论】:

  • OP 声明“输出文件应以制表符分隔的方式显示所有条目”,需要在上面的代码中设置制表符分隔符。
  • @niemmi 非常感谢,我在这个项目中使用了 Python 2,但我用 python 3 进行了尝试,它提供了所需的输出,这当然是完美的 ;)
猜你喜欢
  • 2019-06-20
  • 2012-08-20
  • 2012-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-24
相关资源
最近更新 更多