我有一个需要阅读的大型输入文件,因此我不想使用enumerate
或fo.readlines()
。
for line in fo:
以传统的方式行不通,我会说明原因,但我觉得对此的一些修改就是我现在所需要的。请考虑以下文件:
input_file.txt:
3 # No of tests that will follow
3 # No of points in current test
1 # 1st x-coordinate
2 # 2nd x-coordinate
3 # 3rd x-coordinate
2 # 1st y-coordinate
4 # 2nd y-coordinate
6 # 3rd y-coordinate
...
我需要的是能够读取变量的行块,将元组中的坐标配对,将元组添加到案例列表中,然后返回到从文件中读取新案例。
我想到了这个:
with open(input_file) as f:
T = int(next(f))
for _ in range(T):
N = int(next(f))
for i in range(N):
x.append(int(f.next()))
for i in range(N):
y.append(int(f.next()))
然后将两个列表耦合成一个元组。我觉得必须有一个更清洁的方法来做到这一点。有什么建议吗?
编辑:y坐标必须有一个单独的for循环才能读取。它们是x和y坐标分开n行。所以Read line i;读线(i + n);重复n次 - 对于每种情况。
答案 0 :(得分:3)
这可能不是最短的解决方案,但我相信它“非常优秀”。
def parse_number(stream):
return int(next(stream).partition('#')[0].strip())
def parse_coords(stream, count):
return [parse_number(stream) for i in range(count)]
def parse_test(stream):
count = parse_number(stream)
return list(zip(parse_coords(stream, count), parse_coords(stream, count)))
def parse_file(stream):
for i in range(parse_number(stream)):
yield parse_test(stream)
它将急切地解析单个测试的所有坐标,但每个测试只会在你要求的时候懒得解析。
您可以像这样使用它来迭代测试:
if __name__ == '__main__':
with open('input.txt') as istr:
for test in parse_file(istr):
print(test)
可能需要更好的函数名称来更好地区分渴望和懒惰函数。我现在缺乏命名创造力。
答案 1 :(得分:2)
from itertools import zip_longest
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 zip_longest(*args, fillvalue=fillvalue)
with open(input_file) as archi:
T = int(next(archi))
N = int(next(archi))
points = [ g for g in grouper(map(int,archi),N) ]
print(points) # [(1, 2, 3), (2, 4, 6)]
result = list( zip(*points) )
print(result) # [(1, 2), (2, 4), (3, 6)]
这里我使用石斑鱼阅读N行,获取一个包含所有x和所有y的元组列表,然后使用zip将所有这些组合在一起
答案 2 :(得分:0)
听起来你并没有真正尝试“逐行读取文件”。听起来你想跳过文件,将其视为一个大型列表/数组,但不会引发过多的内存消耗。
你看过mmap模块了吗?
有了这个,您可以使用.find()
之类的方法来查找换行符,可选择从某个偏移量开始(例如刚刚超过当前的测试头)和.seek()
将文件指针移动到您找到的第n个项目然后是.readline()
等等。
mmap
对象共享字符串或字节数组的一些方法和属性,以及文件类对象中的一些方法和属性。因此,您可以使用混合的方法,如.find()
(字符串和字节数组的常规)和.seek()
(用于文件)。
此外,Python内存映射使用操作系统的功能将文件映射到内存中。 (在Linux和类似系统上,这与您的共享库映射到所有正在运行的进程的地址空间的机制相同)。关键是你的内存只用作文件内容的缓存,操作系统将透明地执行必要的I / O加载和释放文件内容的内存缓冲区。
我没有看到找到某个字符或字符串的“第n”个出现的方法......所以没有办法跳到某个行。据我所知,你必须循环.find()
但是你可以使用Python的切片表示法跳回任何这样的行。您可以编写实用程序类/对象以一次扫描1000行终止符,并将它们存储在索引/列表中。然后,您可以使用内存映射切片中的值。