[英]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.