Python如何提高在3GB文件中查找并删除行的效率

3

第一篇文章,您可以尽情提出批评意见...

我的问题: 我有一个包含 1.4 亿行的非常大的文件(文件1)和一个稍小的包含 300 万行的文件(文件2)。我想删除文件1中与文件2匹配的那些行。直觉上,这似乎是一个简单的查找和删除问题,不应该花费太长时间...相对而言。目前我的代码在24G处理器上运行约4天。我希望在几个文件上执行此操作,因此需要改进时间。欢迎任何帮助和评论。

样例文件1:

reftig_0 43 0 1.0
reftig_0 44 1 1.0
reftig_0 45 0 1.0
reftig_0 46 1 1.0
reftig_0 47 0 5.0

示例文件2:

reftig_0 43
reftig_0 44
reftig_0 45

代码:

data = open('file_1', 'r')
data_2 = open('file_2', 'r')
new_file = open('new_file_1', 'w')

d2= {}
for line in data_2:
    line= line.rstrip()
    fields = line.split(' ')
    key = (fields[0], fields[1])
    d2[key]=1

#print d2.keys()
#print d2['reftig_1']
tocheck=d2.keys()
tocheck.sort()
#print tocheck

for sline in data:
    sline = sline.rstrip()
    fields = sline.split(' ')
    nkey = (fields[0],fields[1])
    #print nkey
    if nkey in tocheck:
        pass
    else:
        new_file.write(sline + '\n')
        #print sline

4
你有一枚24GB的处理器?我该从哪里买到呢?:P - nneonneo
如果文件中的数据是有序的(看起来是这样的):为什么不将两个文件并排读取,只写入所有与file2中下一行不匹配的行? - devsnd
我是指RAM,抱歉。文件实际上没有排序,因此最终会失步。 - sbsar
3个回答

4
你的脚本运行缓慢,因为代码行 if nkey in tocheck 是在对 listnkey 进行检查。这是非常慢的,因为它是一次线性搜索(即使 tocheck 已经排序)。
改用 set 来代替:

def getkey(line):
    line = line.rstrip()
    fields = line.split(' ')
    return (fields[0], fields[1])

tocheck = {getkey(line) for line in data_2}

for line in data:
    if getkey(line) not in tocheck:
        new_file.write(line)

结合unutbu的批量写入技巧,你的脚本应该能够运行得非常快。

4

这个可能更好地使用 grep 来处理:

grep -Fvf file2 file1

这样会带走比预期更多的行数...我正在尝试不使用-F。 - sbsar

3

每次一行地将短字符串写入new_file会很慢。通过将内容附加到列表中并仅在列表达到一定长度(例如1000行)时才将其写入new_file,可以减少写入次数。

N = 1000
with open('/tmp/out', 'w') as f:
    result = []
    for x in range(10**7):
        result.append('Hi\n')
        if len(result) >= N:
            f.write(''.join(result))
            result = []

以下是运行 time test.py 得出的不同 N 值时的结果:

|      N | time (sec) |
|      1 |      5.879 |
|     10 |      2.781 |
|    100 |      2.417 |
|   1000 |      2.325 |
|  10000 |      2.299 |
| 100000 |      2.309 |

谢谢大家,我现在只剩下一个小时了! - sbsar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接