我需要读取构造为多行记录的大文件,并写入具有某些索引的文件记录,例如记录号R = 1、2和1093。 如果记录是N = 3行,则相当于逐行读取文件,然后写入行1、2、3和4、5、6和3277、3278、3279(因为每个记录Ri的第一行开始在行号Ri-1 * N + 1处。
我猜一个人可以计算出要写的行,并逐行遍历文件并写那些行。但是,是否可以将连续的第1、2和3行“压缩”到包含记录的生成器对象中,并以某种方式过滤这些记录,或者如果它们枚举为R则将其直接打印到文件中? 伪代码中的内容:
def subset(file_in, file_out, N, R):
with open(file_in, "rt") as fin, open(file_out, "wt") as fout:
line = (line.rstrip() for line in fin)
record = enumerate(zip(line, line, line)) # What if records are of size N
for i, r in record if i in R:
fout.write(r)
如果要将记录大小N作为参数怎么办?
更新示例
file_in的示例(4条记录,每条记录3行):
dslfkj
2
a
dflkj
3
g
fds
2
b
fsdlkj
1
n
然后子集(file_in,file_out,3,[1,3])将给出(file_out)
dslfkj
2
a
fds
2
b
答案 0 :(得分:1)
对于此问题,仅使用楼层划分逐行直接解决此问题就很有意义。
例如:
fin = '''
dslfkj
2
a
dflkj
3
g
fds
2
b
fsdlkj
1
'''
line_gen = (line.rstrip() for line in fin.strip().split())
R = [1, 3]
R = [val - 1 for val in R] #zero indexing
N = 3
for i, line in enumerate(line_gen):
if i // N in R:
print(line)
输出:
dslfkj
2
a
fds
2
b
您的函数可能如下所示:(您可能要检查它是否开箱即用或需要调整。我没有检查文件打开部分。
def subset(file_in, file_out, N, R):
R = [val - 1 for val in R] #zero indexing
with open(file_in, "rt") as fin, open(file_out, "wt") as fout:
line_gen = (line.rstrip() for line in fin)
for i, line in enumerate(line_gen):
if i // N in R:
fout.write(line)
fout.write('\n')
编辑:以下答案与如何使用生成器并将值分组在一起有关。话虽如此,我认为您不需要使用它。但是,如果您仍然愿意,则可以基于它构造函数。
旧答案:
您可以使用列表创建n
对对象的引用,然后使用*
(aka splat) operator解压缩。
例如:
from itertools import zip_longest
line = (x for x in range(100, 132))
n = 3
record = zip(*([line] * n)) #equivalent to *[line, line, line] which is unpacked into zip arguments
for i, r in enumerate(record):
print(i, r)
0 (100, 101, 102)
1 (103, 104, 105)
2 (106, 107, 108)
3 (109, 110, 111)
4 (112, 113, 114)
5 (115, 116, 117)
6 (118, 119, 120)
7 (121, 122, 123)
8 (124, 125, 126)
9 (127, 128, 129)
此外,根据您想对“剩余”行执行的操作,您可能希望使用zip_longest。