在Python中,如何以特定格式将嵌套字典的内容写入文件?

时间:2013-06-20 22:21:06

标签: python output output-formatting

我有一本字典词典,我试图以某种方式输出其中的信息,以便它可用于下游分析。注意:“dict”中的所有键也在“list”中。

for item in list:
for key, value in dict[item].items():
     print item, key, value

这是我最接近我想要的东西,但它还有很长的路要走。理想情况下我想要的是:

     item1  item2  item3  item4
key1 value  value  value  value
key2 value  value  value  value
key2 value  value  value  value

这是否可能?

4 个答案:

答案 0 :(得分:3)

首先,如果我理解你的结构,那么列表只是为外部字典排序键的一种方式,而你的很多复杂性试图将这两者结合起来模拟有序字典。如果是这样,有一种更简单的方法:使用collections.OrderedDict。我最后会回到那里。


首先,您需要获取子词典的所有键,因为这些是您输出的行。

通过评论,听起来dct中的所有子词都具有相同的键,因此您可以将键从任意一个中拉出来:

keys = dct.values()[0].keys()

如果每个子词典可以有不同的键子集,则需要首先通过dct来获取所有键:

keys = reduce(set.union, map(set, dct.values()))

有些人发现reduce难以理解,即使您真的只是将其用作“sum与不同的运营商”。对于他们来说,这里是如何明确地做同样的事情:

keys = set()
for subdct in dct.values():
    keys |= set(subdct)

现在,对于每个键的行,我们需要按照指定的顺序为每个子字典(即外部字典中的每个值)获取一个列,使用列表的元素作为外部字典中的键

因此,对于每个列item,我们希望获得与item中的键对应的外部字典值,然后在生成的子字典中,获取与该行相对应的值key。用英语很难说,但在Python中,它只是:

dct[item][key]

如果你并没有在所有子词典中拥有所有相同的键,那只会稍微复杂一些:

dct[item].get(key, '')

因此,如果您不想要任何标题,它将如下所示:

with open('output.csv', 'wb') as f:
    w = csv.writer(f, delimiter='\t')
    for key in keys:
        w.writerow(dct[item].get(key, '') for item in lst)

要添加标题列,只需将标题(在本例中为key)添加到每个行中:

with open('output.csv', 'wb') as f:
    w = csv.writer(f, delimiter='\t')
    for key in keys:
        w.writerow([key], [dct[item].get(key, '') for item in lst])

请注意,我将genexp转换为列表解析,因此我可以使用列表连接来添加key。将它作为迭代器保留在概念上是更干净的,并且以itertools.chain为前缀,但在像这样的微小迭代的小事件中,我认为这只是让代码更难阅读:

with open('output.csv', 'wb') as f:
    w = csv.writer(f, delimiter='\t')
    for key in keys:
        w.writerow(chain([key], (dct[item].get(key, '') for item in lst)))

您还需要标题行。那更容易;它只是列表中的项目,标题列前面有一个空白列:

with open('output.csv', 'wb') as f:
    w = csv.writer(f, delimiter='\t')
    w.writerow([''] + lst)
    for key in keys:
        w.writerow([key] + [dct[item].get(key, '') for item in lst])

然而,有两种方法可以使事情变得更简单。

首先,您可以使用OrderedDict,因此您不需要单独的键列表。如果您坚持使用单独的listdict,您仍然可以动态构建OrderedDict以使代码更易于阅读。例如:

od = collections.OrderedDict((item, dct[item]) for item in lst)

现在:

with open('output.csv', 'wb') as f:
    w = csv.writer(f, delimiter='\t')
    w.writerow([''] + od.keys())
    for key in keys:
        w.writerow([key] + [subdct.get(key, '') for subdct in od.values()])

其次,您可以构建转置结构:

transposed = {key_b: {key_a: dct[key_a].get(key_b, '') for key_a in dct} 
              for key_b in keys}

然后以明显的顺序迭代它(或使用DictWriter来处理列的排序,并使用其writerows方法来处理行,所以整个事情成为一个单线)。

答案 1 :(得分:1)

要在Python中存储对象以便以后可以重用它们,可以使用shelve模块。这个模块允许您将对象写入一个架子文件并重新打开它并稍后检索它们,但它依赖于操作系统,所以如果你在Mac上制作它以后想要打开它将无法工作它在Windows机器上。

import shelve

shelf = shelve.open("filename", flag='c') 
#with flag='c', you have to delete the old shelf if you want to overwrite it

dict1 = #something
dict2 = #something

shelf['key1'] = dict1
shelf['key2'] = dict2

shelf.close()

从架子上读取对象:

shelf_reader = shelve.open("filename", flag='r')
for k in shelf_reader.keys():
    retrieved = shelf_reader[k]
    print(retrieved) #prints the retrieved dictionary

shelf_reader.close()

答案 2 :(得分:0)

这可能是一个观点问题,但我认为序列化(嵌套)字典的最佳方法之一就是使用JSON格式:

{ "key1" : { "subkey1" : "value1",
             "subkey2" : "value2" },
  "key2" : {"subkey3" : "value3"} }

最好的是,可以使用内置json模块在​​一行中完成(编码您的值或解码它们)!

让我们考虑您的词典是dico变量:

import json
save_file = open('save_file', 'w')
save_file.write( json.dumps(dico) )

Etvoilà:-)!

答案 3 :(得分:0)

如果保证数据被加载回Python,我建议只使用pickle而不是担心格式。如果它将被加载到另一种标准语言中,那么请考虑使用json - 大多数语言的库都可以解析JSON格式数据。

如果你真的需要发明自己的格式,你可以这样做,以CSV格式存储所有子词典中的所有键:

import csv
dict_keys = sorted(dict.keys())
with open("output.csv", "wb") as csvfile:
    writer = csv.writer(csvfile)
    writer.writerow(["Key"] + dict_keys)
    all_keys = reduce(set.union, (set(d) for d in dict.values()))
    for key in sorted(all_keys):
        writer.writerow([key] + [dict[k].get(key, "") for k in dict_keys])