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。另请参阅