什么是用于很长字符串列表的良好数据结构?

时间:2017-04-26 16:35:22

标签: python python-2.7 search text

我有一个非常大的文件(80 GB),每行包含一个句子。我想在这个文件中搜索用户给定的字符串(空格,连字符,要忽略的大小写)。

现在我将文件作为文本,我使用的是grep,但这需要花费很多时间。什么是更好的解决方案?

文本文件内容示例:

 applachian
 rocky mountains
 andes
 sierra nevada
 long mountain ranges of the world

搜索查询示例:

rocky (no match)
sierra nevada (match found)

2 个答案:

答案 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)所有规范化搜索关键字,映射到找到这些关键字的位置。然后,您可以快速检索偏移量和长度,并在真实文件中查找该位置,进行正确的基于==的比较。