Python 查找具有数百万行的文件之间的常用短语
我有两个文件,行数如下:Python 查找具有数百万行的文件之间的常用短语,python,Python,我有两个文件,行数如下: file1 - 110433003 file2 - 4838810 我需要找出这两者之间的共同短语。每行的形式如下: p1 | | | | p2 | | | 文件1的p1可以是文件2中的p2。不幸的是,我写的代码花了太长的时间来完成这项工作 import sys import os if(len(sys.argv)<2): print 'python CommonPhrases.py enFr hrEn commonFile'
file1 - 110433003
file2 - 4838810
我需要找出这两者之间的共同短语。每行的形式如下:
p1 | | | | p2 | | |
文件1的p1可以是文件2中的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')
导入系统
导入操作系统
如果(len(sys.argv)您肯定需要这样的trie。看起来您将花费大部分时间搜索集合以查找匹配项 此外,每当我发现自己试图让python运行得更快时,我就会切换到pypy 它的设置非常简单(只需下载二进制文件,将其放在路径中,然后将#!/usr/bin/env python更改为#!/usr/bin/env pypypy),并为此类任务提供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')
!/usr/bin/env pypypy
导入系统
导入操作系统
sys.path.append('/usr/local/lib/python2.7/dist-packages/PyTrie-0.1-py2.7.egg/'))
从pytrie导入将stringtrie分类为trie
如果(len(sys.argv)这听起来像是一个树问题。也许这个想法可以帮助你
使用树有助于找到常用词。基于创建树的想法,我认为有两种解决方案
树一旦实现,将需要存储一个文件(仅一个文件)的每个字。然后,开始读取第二个文件并搜索树中该文件上的每个字
当然,这个解决方案也有一些问题。在内存中存储这么多单词(或行)的树可能需要大量MB的RAM
假设您设法使用固定数量的RAM来存储数据,因此只计算数据本身(行的字符)。在最坏的情况下,您将需要255^N字节,其中N是最长行的长度(假设您使用的是almos每个字的N扩展组合)。因此,存储长度为10的单词的所有可能组合,您将需要1.16252367019e+24字节的RAM。这是一个很大的问题。请记住,此解决方案(据我所知)是“快速”的,但需要比您可能找到的更多的RAM
所以,另一个非常慢的解决方案是读取文件A的一行,然后将其与文件B的每一行进行比较。它几乎不需要RAM,但需要太多的时间,可能您无法真正等待它
所以,也许另一个解决办法是划分问题
你说你有一个行列表,我们不知道它们是否按字母顺序排序。因此,也许你可以开始读取文件a,并创建新文件。每个新文件将存储,例如,以“a”开头的行,其他以“B”开头的行,等等。然后,对文件B执行相同的操作,结果是有两个以“a”开头的文件lines,一个用于原始A文件,另一个用于原始B文件。然后,将它们与树进行比较
在最好的情况下,行将被平均分割,让您使用内存上的树。在最坏的情况下,您将只以一个文件结束,与启动一个文件相同,因为可能所有行都以“a”开头
因此,如果文件仍然太大,您可以实现一种方法来分割更多的文件,首先,通过行上的第一个字符。然后,以“a”开头的行,将它们分割为“AA”、“AB”、“AC”等,当然,删除之前的分割文件,直到文件足够小,可以使用更好的方法搜索相同的行(可能使用内存上的树)
此解决方案也可能需要很长时间,但可能没有低ram选项那么长,而且不需要太多ram来工作
这些都是我现在能想到的解决方案。可能有效,也可能无效。python有trie实现吗?如果您在类似unix的系统上,并且每个文件只包含一个短语,那么您可以尝试一下。将每个短语放在自己的行中,后跟sort | uniq-c。另请参阅