在Python中写入后删除行
好的,这是我现在的代码:
////////////// = []
for line in datafile:
splitline = line.split()
for item in splitline:
if not item.endswith("JAX"):
if item.startswith("STF") or item.startswith("BRACKER"):
//////////.append( item )
for line in //////////
print /////////////
/////////// +=1
for t in//////
if t in line[:line.find(',')]:
line = line.strip().split(',')
///////////////write(','.join(line[:3]) + '\n')
break
/////////////.close()
/////////////close()
///////////.close()
我想进一步优化一下。这个文件非常大。我希望在把匹配的行写入小文件后,能把这些行从大文件中删除,这样可以减少在大文件中搜索所需的时间。有没有什么建议我该怎么做?
2 个回答
正如我在评论中提到的,我觉得“bigfile”的大小并不会影响计数增加的速度。当你这样遍历一个文件时,Python其实是一次读取一行,按顺序进行的。
在这个时候,你可以进行的优化取决于matchedLines的大小,以及matchedLines中的字符串和你要查找的文本之间的关系。
如果matchedLines很大,你可以通过只进行一次'find'来节省时间:
for line in completedataset:
text = line[:line.find(',')]
for t in matchedLines:
if t in text:
line = line.strip().split(',')
smallerdataset.write(','.join(line[:3]) + '\n')
break
在我的测试中,'find'大约花了300纳秒,所以如果matchedLines有几百万个项目,那就能节省不少时间。
如果你在寻找完全匹配,而不是子字符串匹配,你可以通过使用集合来大幅提高速度:
matchedLines = set(matchedLines)
for line in completedataset:
target = line[:line.find(',')]
## One lookup and you're done!
if target in matchedLines:
line = line.strip().split(',')
smallerdataset.write(','.join(line[:3]) + '\n')
如果不匹配的目标文本看起来和匹配的文本完全不同(比如,大部分目标是随机字符串,而matchedLines是一堆名字),并且matchedLines的长度都超过某个值,你可以尝试通过检查子字符串来聪明地优化。假设所有的matchedLines至少有5个字符长……
def subkeys(s):
## e.g. if len(s) is 7, return s[0:5], s[1:6], s[2:7].
return [s[i:i+5] for i in range(len(s) + 1 - 5)]
existing_subkeys = set()
for line in matchedLines:
existing_subkeys.update(subkeys(line))
for line in completedataset:
target = line[:line.find(',')]
might_match = False
for subkey in subkeys(target):
if subkey in existing_subkeys:
might_match = True
break
if might_match:
# Then we have to do the old slow way.
for matchedLine in matchedLines:
if matchedLine in target:
# Do the split and write and so on.
不过,试图这样做很容易让自己陷入困境,而且这还得看你的数据是什么样子的。
你不能直接在文本文件中删除某一行,因为这样做需要把被删除行后面的所有数据都往上移动,以填补这个空缺,这样会非常低效。
一种方法是先创建一个临时文件,把你想保留的所有行写入这个临时文件中。等你处理完后,删除原来的大文件 bigfile.txt,然后把临时文件重命名为大文件的名字。
另外,如果 bigfile.txt 文件不大,能够放进内存里,你可以把整个文件读到一个列表中,然后从这个列表里删除你不需要的行,最后再把这个列表写回到磁盘上。
从你的代码来看,我猜 bigfile.txt 可能是某种 CSV 文件。如果是这样的话,可能更好的是把它转换成数据库文件,然后用 SQL 来查询。Python 自带了 SQLite 模块,还有很多第三方库可以用来处理其他类型的数据库。