[英]How do I write the contents of nested dictionaries to a file in a certain format?
我有一本字典,我试图以某种方式输出其中的信息,以便它可用于下游分析。 注意: 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
这甚至可能吗?
首先,如果我理解你的结构,列表只是为外部字典排序键的一种方式,你的很多复杂性是试图将这两个一起使用来模拟有序字典。 如果是这样,有一个更简单的方法来做到这一点:使用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 对应的外字典值,然后在生成的子字典中,获取该行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
,因此您不需要单独的键列表。 如果您坚持使用单独的list
和dict
,您仍然可以动态构建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
方法处理行,因此整个事情变成了单行)。
要在 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()
这可能是一个见仁见智的问题,但我认为序列化(嵌套)字典的最佳(也是迄今为止最简单的)方法之一是使用 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) )
等等 :-) !
如果保证将数据加载回 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])
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.