我在Stackoverflow上看到了“有效搜索文件中的字符串”的几个变体,但不完全像我的情况。
我有一个包含相对较大数量(> 300K)字符串的文本文件。绝大多数这些字符串都是多个单词(例如,“Plessy v.Ferguson”,“John Smith”等)。
从那里,我需要搜索一大堆文本文件(一组总计> 10GB的合法文档)并计算这些字符串的实例。
由于搜索字符串的数量,具有多个单词的字符串以及搜索目标的大小,许多“标准”解决方案似乎都落在了路边。
有些事情可以简化问题 -
我不需要复杂的标记化/词干化等等(例如我唯一关心的是“Plessy v.Ferguson”,不需要担心“Plessy”,“Plessy et.al 。“等。)
会有一些重复(例如,多个名为“John Smith”的人),但是,这对于这个数据集来说不是一个非常重要的统计问题所以...如果多个John Smith被混淆了一个单一的记录,现在还可以。
我只需要计算这些特定的实例;我不需要返回搜索结果
1个文件中的10个实例与10个文件中的每个实例相同
有关快速/肮脏方法解决此问题的任何建议吗?
我调查了NLTK,Lucene&其他人,但他们似乎对我试图解决的问题有点过分。我应该把它搞砸并将所有内容导入数据库吗?暴力迫害它300k倍? ;)
我首选的开发工具是Python。
要搜索的文档主要是这样的法律文档 - http://www.lawnix.com/cases/plessy-ferguson.html
预期结果是针对这些文档引用案例的频率的统计数据 - “Plessey v.Ferguson:15”
答案 0 :(得分:2)
解决此问题的一种简单方法是使用您的查询构建一个trie(只是一个前缀树,内部包含单个字符的节点列表),当您搜索10gb文件时,您将以递归方式浏览树。火柴。
通过这种方式,您可以在搜索大文件中的每个字符位置时尽早删除很多选项,同时仍在搜索整个解决方案空间。
时间性能非常好(与许多其他更复杂的解决方案一样好)并且您只需要足够的空间来存储树(比整个字符串数组少得多)和一个小缓冲区大文件。绝对要比300倍数据库更好...
答案 1 :(得分:0)
您必须处理几个约束,这会使这成为一个复杂的问题。
我建议编写一个多线程/多进程python应用程序。子进程的库是无痛的。让每个进程读入一个文件,并按照Blindy的建议读取解析树。完成后,它会将结果返回给父级,父级会将结果写入文件。
这会占用尽可能多的资源,同时允许扩展。如果您将它粘贴在beowulf群集上,它将透明地共享您的cpus中的进程。
唯一的关键点是硬盘IO。将其分解为不同硬盘驱动器上的块,并在每个进程完成后,启动一个新文件并加载文件。如果您使用的是Linux,则所有文件可以共存于同一文件系统命名空间中,并且您的程序不会知道其中的差异。
答案 2 :(得分:0)
丑陋的暴力解决方案无效。
通过你的文件计算一次grep并推断300k greps所需的时间(如果你有许多机器可以尝试并行化它),这是否可行?我的猜测是300k搜索是不可行的。例如,通过~50 Mb的文件搜索一次搜索大约需要约5s,所以对于10 Gb,你期望~1000s,然后重复300k次意味着你将在大约10年内使用一台计算机完成。您可以并行化以获得一些改进(受一台计算机上的磁盘io限制),但仍然非常有限。我假设您希望任务在几个小时而不是几个月内完成,因此这不太可能是一个解决方案。
所以你需要以某种方式索引文档。 Lucene(通过pythonsolr说)或Xapian应该适合您的目的。索引文档,然后搜索索引文档。
答案 3 :(得分:0)
您应该使用组模式匹配算法,这些算法使用动态算法来重用评估。即Aho-Corasick。实施
答案 4 :(得分:-1)
我不知道这个想法是否非常愚蠢,请告诉我......
将要搜索的文件划分为合理大小的数字10/100/1000 ...并且对于每个“块”,使用可用于SW的索引SW。在这里,我正在考虑ctags gnu global或ptx
实用程序或使用此SO post中描述的技术。
使用这种技术,您“只”需要在索引文件中搜索目标字符串。