如何优化大文本词邻近检测代码及实现多词对邻近检测
问题1:大文本处理速度优化方案
针对大文本场景,核心优化逻辑是减少重复计算和提升查询效率,具体优化点如下:
- 单次预处理文本:原代码每次调用查询都会重新拆分文本为单词,大文本下重复拆分耗时极高。改为提前将整个文本拆分为小写单词列表,后续所有操作基于该列表执行。
- 构建词-索引映射字典:提前遍历单词列表,记录每个词对应的所有出现索引(如
{'expression': [7, 17], 'same': [5], ...}),后续查询词的位置无需再遍历整个列表,直接通过字典O(1)获取。 - 避免冗余上下文生成:如果仅需检测邻近关系,无需生成上下文切片列表,直接操作索引即可大幅节省内存和计算开销。
问题2:多词对邻近检测实现
要检测列表A中任意词与列表B中任意词是否满足"间隔不超过5个词"(即两词索引差的绝对值≤6——间隔5个词时,索引差为6),可以通过以下步骤实现:
- 分别收集列表A和列表B中所有词的出现索引
- 对其中一个索引列表排序,使用二分查找快速判断是否存在符合范围的索引(比暴力遍历更高效)
- 遍历其中一个列表的所有索引,检查是否有另一个列表的索引落在
[当前索引-6, 当前索引+6]范围内
整合优化后的完整代码
import re import bisect def preprocess_text(text): # 一次性拆分文本为小写单词列表,大文本场景仅执行一次 return [word.lower() for word in re.findall(r'\w+', text)] def build_word_index_map(words): # 构建词到所有出现索引的映射字典 index_map = {} for idx, word in enumerate(words): if word not in index_map: index_map[word] = [] index_map[word].append(idx) return index_map def check_cross_list_proximity(index_map, list_a, list_b, max_gap=5): # max_gap为间隔的最大词数,对应索引差阈值为max_gap + 1 threshold = max_gap + 1 # 收集列表B中所有词的索引并排序,用于二分查找 b_indices = [] for word in list_b: b_indices.extend(index_map.get(word, [])) b_indices.sort() # 遍历列表A的所有索引,检查是否有B的索引在邻近范围内 for word in list_a: a_indices = index_map.get(word, []) for a_idx in a_indices: # 找B索引中第一个≥a_idx - threshold的位置 left = bisect.bisect_left(b_indices, a_idx - threshold) # 找B索引中第一个> a_idx + threshold的位置 right = bisect.bisect_right(b_indices, a_idx + threshold) # left < right说明存在符合条件的B索引 if left < right: return True, (a_idx, b_indices[left]) return False, None # 示例使用 if __name__ == "__main__": text = ("If you want to use the same regular expression more than once, you should compile it into a regular expression object. ") # 预处理文本 words = preprocess_text(text) # 构建索引映射 word_index_map = build_word_index_map(words) # 多词对检测示例 list_a = ["expression", "banana", "same"] list_b = ["once", "split", "use"] is_proximal, positions = check_cross_list_proximity(word_index_map, list_a, list_b) if is_proximal: a_word = words[positions[0]] b_word = words[positions[1]] print(f"检测到邻近词对:{a_word} 和 {b_word},索引分别为{positions[0]}和{positions[1]}") else: print("未检测到符合条件的邻近词对")
额外说明
- 代码中使用
bisect模块进行二分查找,相比暴力遍历索引,在词出现次数较多时效率提升明显 - 预处理和索引映射只需执行一次,后续多次检测都可复用,非常适合大文本的批量检测场景
- 如果需要提取邻近词的上下文,可以在检测到符合条件的索引后,再根据索引截取对应的单词切片
内容的提问来源于stack exchange,提问作者Misclogo
相关产品推荐
相关产品推荐

