一般来说,您希望预处理大量不变的数据以加快重复搜索的速度。但是你说得太少了,无法提出明显实用的建议。比如:这些字符串有多长?什么是字母表(例如,7 位 ASCII 或完整的 Unicode?)?总共有多少个字符?字母表中的字符是否同样可能出现在每个字符串位置,或者分布是否高度倾斜?如果是这样,怎么做?以此类推。
这是关于最简单的索引类型,构建一个条目数等于所有string_data 中唯一字符数的字典。它将每个字符映射到包含该字符的字符串的string_data 索引集。然后,可以将关键字的搜索限制为现在预先知道包含关键字第一个字符的唯一 string_data 条目。
现在,根据您所说的无法猜到的细节,可能即使是这种适度的索引也会消耗比您拥有的更多的 RAM - 或者它是可能它已经足以让您获得所需的 6 倍加速:
# Preprocessing - do this just once, when string_data changes.
def build_map(string_data):
from collections import defaultdict
ch2ixs = defaultdict(set)
for i, s in enumerate(string_data):
for ch in s:
ch2ixs[ch].add(i)
return ch2ixs
def find_partial_matches(keywords, string_data, ch2ixs):
for keyword in keywords:
ch = keyword[0]
if ch in ch2ixs:
result = []
for i in ch2ixs[ch]:
if keyword in string_data[i]:
result.append(i)
if result:
print(repr(keyword), "found in strings", result)
然后,例如,
string_data = ['banana', 'bandana', 'bandito']
ch2ixs = build_map(string_data)
find_partial_matches(['ban', 'i', 'dana', 'xyz', 'na'],
string_data,
ch2ixs)
显示:
'ban' found in strings [0, 1, 2]
'i' found in strings [2]
'dana' found in strings [1]
'na' found in strings [0, 1]
例如,如果您仍然有足够的 RAM,但需要更快的速度,并且愿意放弃(可能很愚蠢 - 但不能从这里猜测)1 字符匹配,您可以改为索引二元组(相邻字母对)。
在限制中,您可以使用string_data 构建一个尝试,这将需要大量 RAM,但可以将搜索嵌入关键字的时间减少到与关键字中的字符数成正比的操作数,与string_data 中有多少个字符串无关。
请注意,您确实应该找到摆脱这种情况的方法:
results_boolean = [keyword in n for n in string_data]
为每个关键字搜索构建一个包含超过 1000 万个条目的列表会使每次搜索都变得昂贵,无论您多么巧妙地索引数据。
注意:可能对上述内容的实际改进是将搜索限制为包含所有关键字字符的字符串:
def find_partial_matches(keywords, string_data, ch2ixs):
for keyword in keywords:
keyset = set(keyword)
if all(ch in ch2ixs for ch in keyset):
ixs = set.intersection(*(ch2ixs[ch] for ch in keyset))
result = []
for i in ixs:
if keyword in string_data[i]:
result.append(i)
if result:
print(repr(keyword), "found in strings", result)