我写了一个程序来解决你的问题。它生成一个类,该类保存要读取的每个CSV文件的信息,包括要从中读取的列。然后是一个简单的CSV文件列表,从每个文件中读取一行。
因为您说它需要一直返回行,直到读取所有输入文件,所以它会返回到达末尾的输入文件的伪值。它一直读取行,直到完成所有输入文件。
而且,这个程序一次只需要在内存中保存一行。所以它甚至可以处理大型CSV文件,而不需要太多内存。
最初,对于丢失的数据,我有一个-1的伪值。现在我看到你添加了一个例子,你只是想没有价值。我已经将程序从使用-1改为在没有数据时使用空字符串。
其中一个设计目标是使其可扩展。现在您需要前两列,但是如果以后需要其中一个文件中的列0、3和7呢?所以每个文件都有一个列列表。
实际上,我并没有编写代码将输出文件重命名为原始文件名,但这很容易添加。
理想情况下,整个过程都将打包到一个类中,在这个类中,您可以迭代一个类实例,然后使用来自所有输入文件的列将一行放在一起。我没有花额外的时间去做,但如果你要长期使用这个,你可能会想这么做。另外,我从不费心关闭任何输入文件,因为我认为程序将在我们写入输出文件后结束,然后所有文件都将关闭;但理想情况下,我们应该在使用它们后关闭所有文件!import csv
fname_in = "combined.csv"
fname_out = "combined.tmp"
lst_other_fnames = [str(x) + ".csv" for x in range(1, 3)]
no_data = ''
def _no_data_list(columns):
return [no_data for _ in columns]
class DataCsvFile(object):
def __init__(self, fname, columns=None):
self.fname = fname
self.f = open(fname)
self.reader = csv.reader(self.f)
self.columns = columns
self.done = False
def next_columns(self):
if self.done:
return _no_data_list(self.columns)
try:
item = next(self.reader)
except StopIteration:
self.done = True
return _no_data_list(self.columns)
return [item[i] for i in self.columns]
# want all columns from original file
data_csv_files = [DataCsvFile(fname_in, range(5))]
# build list of filenames and columns: want first two columns from each
data_csv_files.extend(DataCsvFile(fname, range(2)) for fname in lst_other_fnames)
with open(fname_out, "w") as out_f:
writer = csv.writer(out_f)
while True:
values = []
for df in data_csv_files:
columns = df.next_columns()
values.extend(columns)
if not all(df.done for df in data_csv_files):
writer.writerow(values)
else:
break