我有一个非常大的文件(80 GB),每行包含一个句子。我想在这个文件中搜索用户给定的字符串(空格,连字符,要忽略的大小写)。
现在我将文件作为文本,我使用的是grep,但这需要花费很多时间。什么是更好的解决方案?
文本文件内容示例:
applachian
rocky mountains
andes
sierra nevada
long mountain ranges of the world
搜索查询示例:
rocky (no match)
sierra nevada (match found)
答案 0 :(得分:1)
根据您的评论,您正在搜索整个句子:
建立前缀索引。
对文件进行排序。接下来,处理您的文件一次。计算将搜索减少到1000个句子所需的前缀长度。也就是说,你需要在给定句子的大约1000个句子中获得多少个前缀字符。
例如:“The”可能是英语中常见的起始词。但是“快速”可能已经足够接近了,因为“q”是低频的,就像“快速的棕色狐狸......等等”。
这样做的一种方法是将所有前缀放到一定长度(例如40)到Collections.counter中。找到每个长度的最大计数,并选择您的长度,使最大值<= 1000.可能还有其他方法。 ; - )
现在,再次处理该文件。构建一个单独的索引文件,由前缀长度(在文件头中),前缀和偏移组成。所有以前缀K开头的句子都以偏移量V开头。因为文件已排序,所以索引也将被排序。
您的程序可以将索引读入内存,打开文件并开始处理搜索。对于每次搜索,请删除前缀,在索引中查找,搜索文件偏移量,然后扫描匹配。
答案 1 :(得分:1)
您可以通过将句子映射到哈希来构建可分析数据库,然后您可以在潜在位置搜索数据。
from collections import defaultdict
from cStringIO import StringIO
DATA = """applachian
rocky mountains
andes
sierra nevada
long mountain ranges of the world"""
def normalize(sentence):
return "".join(sentence.lower().strip())
def create_db(inf):
db = defaultdict(list)
offset = 0
for line in inf:
l = len(line)
db[hash(normalize(line))].append((offset, l))
offset += l
return db
def main():
db = create_db(StringIO(DATA))
# save this db, and in a different script, load it to retrieve:
for needle in ["rocky", "sierra nevada"]:
key = hash(normalize(needle))
for offset, length in db.get(key, []):
print "possibly found at", offset, length
if __name__ == '__main__':
main()
这证明了这个想法:您构建了一个数据库(例如存储为pickle)所有规范化搜索关键字,映射到找到这些关键字的位置。然后,您可以快速检索偏移量和长度,并在真实文件中查找该位置,进行正确的基于==的比较。