所以我有一个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))}
但是由于事情没有正确安排,这不起作用。有些数字是其他数字的子键,字母不合适等等。我还没有进入出口部分。有任何想法吗?
答案 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=''
。)