如何在Python中将所有偶数行从一个文件复制到新文件?
当我想要从一个文件复制到另一个文件的非常精确的行数时,偶数只是一个例子,但它应该是一个很好的例子。
我使用它,但效率非常低(大约需要5分钟):
# foo.txt holds 200,000 lines with 300 values
list = [0, 2, 4, 6, 8, 10..... 199996, 199998]
newfile = open(savefile, "w")
with open("foo.txt", "r") as file:
for i, line in enumerate(file):
if i in list:
newfile.write(line)
newfile.close()
如果能解释为什么这么慢,我也会很感激:逐行阅读(大约15秒),并且手册也会建议。
编辑:我的道歉;我不是在寻找具体的奇数/偶数例子;它仅仅是为了解决如何处理200k值中的大约100k而不是简单的顺序。除了找到更有效的方法来处理奇数/偶数之外,这里的I / O问题没有通用解决方案吗?再次为此提出道歉。
答案 0 :(得分:2)
一直在寻找的是list
。为了确定i
是否在list
中,它必须扫描整个列表以确保它不存在。如果你真的只关心偶数,你可以简单地使用if i % 2 == 0
,但如果你有一组特定的行号,你应该使用set
,它有O(1)成员资格测试,例如
keep = {1, 5, 888, 20203}
然后
if i in keep:
答案 1 :(得分:1)
你花费了大量的时间创作,然后反复搜索(在每一行!!!)那个怪异的list
。只需逐行读取第一个文件并跳过其他文件。您可以使用切换标记执行此操作,或者只检查行号是否可以被2整除(在我看来更清晰)。
for i, line in enumerate(file):
if i % 2 == 0:
newfile.write(line)
编辑以回复您的修改:您的问题现在是“如何从文件中复制任意行?”这很大程度上取决于如何定义这些任意行。答案仍然是不来使用“通缉”行号列表,因为搜索该列表需要很长时间,而且您必须在每一行搜索它。
如果目标本质上是能够从文件中选择随机行,则可以使用类似于当前设置的内容,但使用set
代替list
来快速查找。 通用案例概念验证解决方案可能如下所示:
import random
# Pick 5000 random lines
wanted_lines = set(random.sample(range(200000), 5000)) # Use a set!
for i, line in enumerate(file):
if i in wanted_lines: # average-case O(1)
newfile.write(str(line)+'\n')
答案 2 :(得分:1)
我假设您的list
是预定义的,并且可以包含任何可能的行索引序列,例如,不一定是每第N行。
第一个可能的瓶颈是您正在进行O(n)列表搜索(i in list
)200000次。将列表转换为字典应该有帮助:
listd = dict.fromkeys(list)
.
.
# this is O(1) instead of O(n)
if i in listd:
或者,如果您知道list
已排序,或者您可以对其进行排序,只需跟踪下一行索引:
list = [0, 2, 4, 6, 8, 10..... 199996, 199998]
nextidx = 0
newfile = open(savefile, "w")
with open("foo.txt", "r") as file:
for i, line in enumerate(file):
if i == list[nextidx]:
newfile.write(line)
nextidx += 1
newfile.close()
答案 3 :(得分:0)
这样的事情?
flag = False
with open("test_async_db_access.py", "r") as file:
for line in file:
if flag:
print line
flag = not flag
这避免了必须使用大型列表
编辑:如果它是您想要的任意行列表,那么使用地图{},如DSM的答案,这将在O(1)时间内执行'in'而不是O(n)。