2016-07-10 45 views
1

我有2个文件:文件A包含200 000行;文件B包含4 000 000行。所以,我想比较这些文件并打印其不在文件B.Python:最好的方法来比较2文本文件?

例如线路: 文件:

1 
    2 
    3 

文件B:

1 
    4 
    5 
    6 
    7 

输出:

2 
    3 

而下面是我的代码:

for line in open ('C:/A.txt'): 
    if line not in open ('C:/B.txt'): 
     print (line) 

此代码有效,但需要很长时间才能完成。那么,如何加快代码过程?

任何帮助将不胜感激! :)

+1

你有没有进去看了['filecmp'模块(HTTPS ://docs.python.org/3/library/filecmp.html)? – karthikr

+0

这是[渐近复杂度](https://en.wikipedia.org/wiki/Asymptotic_computational_complexity)的典型例子,通常称为[Big O notation](https://en.wikipedia.org/wiki/Big_O_notation )。'not in'语句必须每次读取整个文件,即O(n)(线性时间 - 工作量与输入长度成正比)。既然你在第一个文件中为每一行调用一次,那么你要做的线性工作量为线性(O(n))次。因此,您的算法需要O(n)x O(n)或O(n^2)时间运行 - 也称为二次时间。 – dimo414

回答

2

建立一套公正的文件B中的行的哈希值 - 并将A中的行与此集中的行进行比较 -

这样的集合大约需要100兆内存,因此应该放在笔记本或内存中的内存中rkstation:

linesB = {hash(line) for line in open("fileB"))} 
for line in open("fileA"): 
    if hash(line) not in linesB: 
     print (line) 

主要的速度在这里是不像搜索线性内FILEB一条线,它是只读一次 - 每行一组,它具有恒定的查找时间提供。因此,你从大约200,000×4,000,000比较(O(m×n))下降到〜200.000比较(O(m×1))。

更不用说不需要将数据从系统移动到程序存储器200,000次左右。

通过只保留B中的hash行,您可以避免将fileB的所有文本信息保留在内存中 - 每个散列(在64位系统中)只需24字节 - 而不是文本信息本身(取决于每个行长)+它的散列。

+0

谢谢你给我的代码。使用散列之后,代码运行速度非常快:) – NGuyen

+0

使它快速运行的原因是nltthe'hash' - 正在读取第二个文件,并将其放入一个'set'中,该文件具有恒定的查找时间。 – jsbueno

+0

不能保证两条不同的线不会散列到相同的值,特别是线长度增加时。给定字符串的默认哈希随机化,这在运行之间甚至不是确定性的。对于保证,您需要将字符串本身添加到集合中(当发生散列冲突时将其探测到哈希表中),这会大大增加内存要求。 – eryksun

1

一个更快的方法是打开文件一次,并且使用一组:

with open('C:/A.txt') as a: 
    with open('C:/B.txt') as b: 
     lines = set(b) 
    for line in a: 
     if line not in lines: 
      print(line) 

也许一个更好的方式是这样的:

with open('C:/A.txt') as a, open('C:/B.txt') as b: 
    lines = set() 
    for line in a: 
     if line not in lines: 
      for line_b in b: 
       lines.add(line_b) 
       if line_b == line: 
        break 
      else: 
       print(line) 
1

您可以使用set difference操作来获取所有在这些文件中不匹配的行。

with open('A.txt') as a: 
    contentA = set(a) 

with open('B.txt') as b: 
    contentB = set(b) 

print(contentA - contentB) 

编辑: 相反的操作,要打印的是不是一个文件B的内容现在只是

print(contentB - contentA)