从CSV文件导入/导出嵌套字典

时间:2014-04-06 22:59:32

标签: python csv dictionary nested

所以我有一个CSV文件,其数据排列如下:

X,a,1,b,2,c,3
Y,a,1,b,2,c,3,d,4
Z,l,2,m,3

我想导入CSV以创建嵌套字典,使其看起来像这样。

data = {'X' : {'a' : 1, 'b' : 2, 'c' : 3}, 
        'y' : {'a' : 1, 'b' : 2, 'c' : 3, 'd' : 4},
        'Z' : {'l' : 2, 'm' :3}}

在我写的程序中更新字典后(我得到了那部分),我希望能够将字典导出到同一个CSV文件中,覆盖/更新它。但是我希望它与前一个CSV文件的格式相同,以便我可以再次导入它。

我一直在玩导入,并且到目前为止还有这个

import csv
data = {}
with open('userdata.csv', 'r') as f:    
    reader = csv.reader(f)
    for row in reader:
       data[row[0]] = {row[i] for i in range(1, len(row))}

但是由于事情没有正确安排,这不起作用。有些数字是其他数字的子键,字母不合适等等。我还没有进入出口部分。有任何想法吗?

4 个答案:

答案 0 :(得分:2)

由于您对保留订单不感兴趣,因此应该采用相对简单的方法:

import csv

# import
data = {}
with open('userdata.csv', 'r') as f:
    reader = csv.reader(f)
    for row in reader:
        a = iter(row[1:])
        data[row[0]] = dict(zip(a, a))

# export
with open('userdata_exported.csv', 'w') as f:
    writer = csv.writer(f)
    for key, values in data.items():
        row = [key] + [value for item in values.items() for value in item]
        writer.writerow(row)

通过只调用csv.writer的{​​{1}}方法并将generator expression传递给{{3}},可以更有效地完成后者。

writerows()

答案 1 :(得分:0)

您可以使用itertools中的grouper食谱:

def grouper(iterable, n, fillvalue=None):
    "Collect data into fixed-length chunks or blocks"
    # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx
    args = [iter(iterable)] * n
    return itertools.izip_longest(fillvalue=fillvalue, *args)

这会将您的数据分组到您想要的a1 / b2 / c3对中。所以你可以在你的循环中做data[row[0]] = {k: v for k, v in grouper(row[1:], 2)}

答案 2 :(得分:0)

from collections import defaultdict

data_lines = """X,a,1,b,2,c,3
Y,a,1,b,2,c,3,d,4
Z,l,2,m,3""".splitlines()

data = defaultdict(dict)

for line in data_lines:
# you should probably add guards against invalid data, empty lines etc.
    main_key, sep, tail = line.partition(',')
    items = [item.strip() for item in tail.split(',')]
    items = zip(items[::2], map(int, items[1::2])
    # data[main_key] = {key : value for key, value in items}
    data[main_key] = dict(items)

print dict(data)
# {'Y': {'a': '1', 'c': '3', 'b': '2', 'd': '4'}, 
#  'X': {'a': '1', 'c': '3', 'b': '2'}, 
#  'Z': {'m': '3', 'l': '2'}
# }

答案 3 :(得分:0)

我很懒,所以我可能会做这样的事情:

import csv
data = {}

with open('userdata.csv', 'rb') as f:    
    reader = csv.reader(f)
    for row in reader:
        data[row[0]] = dict(zip(row[1::2], map(int,row[2::2])))

是有效的,因为row[1::2]给出了从1开始的每个其他元素,而row[2::2每隔一个元素从2开始。zip生成这些元素的元组对,然后我们传递到dict。这给了

{'Y': {'a': 1, 'c': 3, 'b': 2, 'd': 4}, 
 'X': {'a': 1, 'c': 3, 'b': 2}, 
 'Z': {'m': 3, 'l': 2}}

(请注意,我已将open更改为使用'rb',这适用于Python 2:如果您使用3,则需要'r', newline=''。)