如何将嵌套字典的内容以某种格式写入文件?

问题描述 投票:1回答:4

我有一个词典的字典,我试图以某种方式输出其中的信息,以便将其用于下游分析。注意: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

这甚至有可能吗?

python output output-formatting
4个回答
3
投票

首先,如果我了解您的结构,该列表只是一种排序外部字典键的方法,而您的许多复杂性都试图将这两个字典一起使用以模拟一个有序字典。如果是这样,有一种更简单的方法:使用collections.OrderedDict。最后我会再说。


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

从注释看来,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相对应的值。用英语很难说,但是在Python中,只是:

key

如果您实际上在所有子词典中都没有相同的键,那只会稍微复杂一点:

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

注意,我已将genexp转换为列表理解,因此我可以使用列表串联在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]) 之前。从概念上讲,将其保留为迭代器更干净,并以key开头,但是在像这样的琐碎情况下,只有很小的可迭代对象,我认为这只会使代码更难阅读:

itertools.chain

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

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} 方法处理行,因此整个过程变成了单行)。


1
投票

要在Python中存储对象,以便以后可以重新使用它们,可以使用DictWriter模块。这个模块可让您将对象写入到机架文件中,然后重新打开它并在以后检索对象,但是它依赖于操作系统,因此如果说您是在Mac上创建的,后来又想打开它,它将无法正常工作在Windows计算机上。

DictWriter

要从架子上读取对象:

writerows

0
投票

这可能是一个见解,但我认为序列化(嵌套的)字典的最佳方法(到目前为止也是最简便的方法之一是使用JSON格式:

shelve

最好的是,可以使用内置的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() 变量:

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

Etvoilà:-)!


0
投票

如果确保将数据加载回Python,我建议您仅使用json,而不用担心格式。如果要将其加载到另一种标准语言中,请考虑改用dico-大多数语言都有用于解析JSON格式数据的库。

也就是说,如果您确实需要发明自己的格式,则可以执行以下操作以CSV格式存储所有子词典中的所有键:

import json
save_file = open('save_file', 'w')
save_file.write( json.dumps(dico) )
© www.soinside.com 2019 - 2024. All rights reserved.