2016-07-10 46 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)