簡體   English   中英

在具有數百萬行的文件之間查找常用短語

[英]Finding common phrases between files with millions of lines

我有兩個文件,其行數如下:

file1 - 110433003
file2 - 4838810

我需要在這些之間找到共同的短語。 每行的格式為:

p1 ||| p2 ||| .......

file1的p1可以是file2中的p2。 不幸的是,我編寫的代碼花費的時間太長了。

import sys
import os

if(len(sys.argv)<2):
        print 'python CommonPhrases.py enFr hrEn commonFile'
        sys.exit()
enFr = open(sys.argv[1],'r')
hrEn = open(sys.argv[2],'r')
common = open(sys.argv[3],'w')
sethrEn = set([])
setenFr= set([])
for line in hrEn:
        englishPhrase = line.split(' ||| ')[1]
        sethrEn.add(englishPhrase)

for line in enFr:
        englishPhrase = line.split(' ||| ')[0]
        if(englishPhrase in sethrEn):
                common.write(englishPhrase+'\n')

有更快的方法嗎?

謝謝

您肯定需要像這樣的東西。 似乎您將花費大部分時間在該集合中尋找匹配項。

同樣,每次我發現自己試圖使python更快時,我都會切換到pypy。 http://pypy.org/ )非常容易設置(只需下載二進制文件,將其放在您的路徑中,然后將#!/ usr / bin / env python更改為#!/ usr / bin / env pypy),然后可以使此類任務的加速范圍提高5-10倍。

有關使用PyTrie的參考實現,請參見下文。

#!/usr/bin/env pypy

import sys
import os
sys.path.append('/usr/local/lib/python2.7/dist-packages/PyTrie-0.1-py2.7.egg/')
from pytrie import SortedStringTrie as trie

if(len(sys.argv)<2):
        print 'python CommonPhrases.py enFr hrEn commonFile'
        sys.exit()
enFr = open(sys.argv[1],'r')
hrEn = open(sys.argv[2],'r')
common = open(sys.argv[3],'w')

sethrEn = trie()

for line in hrEn:
        englishPhrase = line.strip().split(' ||| ')[1]
        sethrEn[englishPhrase] = None

for line in enFr:
        englishPhrase = line.strip().split(' ||| ')[0]
        if(englishPhrase in sethrEn):
                common.write(englishPhrase+'\n')

請注意,它需要最少的更改(4行),您將需要安裝PyTrie 0.1。 在我的ubuntu系統上,“ sudo easy_install PyTrie”做到了。

希望能有所幫助。

這聽起來像是樹上的問題。 也許這個想法可以幫助您。

使用樹可以幫助找到常用詞。 我認為基於創建樹的想法可以有兩種解決方案。

一棵樹一旦實現,將需要存儲一個文件(僅一個文件)的每個單詞。 然后,開始讀取第二個文件並在樹中搜索該文件上的每個單詞。

當然,該解決方案存在一些問題。 在這樣數量的單詞(或行)的存儲器上存儲樹可能需要大量MB RAM。

讓我們假設您設法使用固定數量的RAM存儲數據,因此,僅對數據本身(行的字符)進行計數。 在最壞的情況下,您將需要255 ^ N個字節,其中N是最長行的長度(假設您使用N擴展的每個單詞組合都使用almos)。 因此,存儲長度為10的字的所有可能組合,您將需要1.16252367019e + 24字節RAM。 好多 請記住,這種解決方案(據我所知)是“快速的”,但是需要更多的RAM,而您可能找不到。

因此,另一種非常慢的解決方案是讀取文件A的一行,然后將其與文件B的每一行進行比較。它幾乎不需要RAM,但是需要太多時間,也許您將無法真的等一下。

因此,也許另一個解決方案是划分問題。

您說您有一個行列表,我們不知道它們是否按字母順序排序。 因此,也許您可​​以開始讀取文件A,然后創建新文件。 例如,每個新文件都將存儲'A'起始行,以'B'開頭的其他行等。然后,對文件B進行相同的操作,結果兩個文件以'A'開頭行,一個用於原始A文件,另一個用於原始B文件。 然后,將它們與一棵樹進行比較。

在最佳情況下,行將被平均分割,從而使您可以在內存中使用樹。 在最壞的情況下,您將只完成一個文件,與開始的A文件相同,因為可能所有行都以“ A”開頭。

因此,也許,您可以采用一種方法來分割更多的文件(如果它們仍然太大),首先,按行中的第一個字符。 然后,以“ A”開頭,將它們分為“ AA”,“ AB”,“ AC”等,當然,刪除先前的除法文件,直到獲得足夠小的文件以使用更好的方法搜索相同的文件為止。行(可能在內存上使用樹)。

此解決方案也可能需要很長時間,但可能需要很短的時間,因為低內存選項,而且不需要太多內存即可工作。

這些是我現在可以想到的解決方案。 也許他們工作了,也許沒有。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM