水平编写CSV

时间:2013-07-31 18:37:28

标签: python csv

假设我们正在从具有多个键值对的某些源读取数据。我们使用以下列表作为示例:

[{'key0': 'key0_value0', 'key1': 'key1_value0'},
 {'key0': 'key0_value1', 'key1': 'key1_value1'}]

从该列表中读取第一项应该会产生如下所示的CSV:

key_header | 0
---------------------------
key0       | key0_value_0
key1       | key1_value_0

现在阅读第二项应该会产生以下结果:

key_header | 0            | 1
----------------------------------------
key0       | key0_value_0 | key0_value_1
key1       | key1_value_0 | key1_value_1

这是水平的,直到直到。写这个的算法超出了我的范围,我不确定the csv module是否可行,因为它似乎假设数据一次写入一行。

2 个答案:

答案 0 :(得分:5)

您必须先收集所有“列”,然后写。您可以通过将所有内容转换为列表列表来执行此操作,然后使用zip(*columns)将列列表转置为行列表:

columns = [['key_header'] + sorted(inputlist[0].keys())]  # first column

for i, entry in enumerate(inputlist):
    columns.append([i] + [entry[k] for k in columns[0][1:]])

with open(outputfilename, 'wb') as output:
    writer = csv.writer(output)
    writer.writerows(zip(*columns))

显示行输出的演示:

>>> from pprint import pprint
>>> inputlist = [{'key0': 'key0_value0', 'key1': 'key1_value0'},
...  {'key0': 'key0_value1', 'key1': 'key1_value1'}]
>>> columns = [['key_header'] + sorted(inputlist[0].keys())]  # first column
>>> for i, entry in enumerate(inputlist):
...     columns.append([i] + [entry[k] for k in columns[0][1:]])
... 
>>> pprint(zip(*columns))
[('key_header', 0, 1),
 ('key0', 'key0_value0', 'key0_value1'),
 ('key1', 'key1_value0', 'key1_value1')]

答案 1 :(得分:1)

无法逐步编写列,因为这不是文本文件(CSV文件是其子集)的工作方式。您不能附加到文件中间的行/行;所有你能做的就是在最后附加新行。

但是,我不知道为什么你还需要这样做。只需将列表转置到内存中,然后逐行写入。

例如:

values = [{'key0': 'key0_value0', 'key1': 'key1_value0'},
          {'key0': 'key0_value1', 'key1': 'key1_value1'}]
transposed = zip(*(x.items() for x in values))
grouped = ([pairs[0][0]] + [pair[1] for pair in pairs] for pairs in transposed)
writer.writerows(grouped)

仅仅转置items还不够,因为您最终会为每个值提供key0的副本,而不是仅仅一个副本。这就是grouped的用途。