如何用re.search从Python字典中提取指定短语及对应坐标
匹配短语并提取对应坐标的解决方案
问题背景
给定如下Python字典,键是完整语句,值是元组列表,列表中每个元素对应键里每个单词的坐标(比如Policy对应第一个坐标元组,general对应第二个,以此类推):
ip_dict = { "Policy general commercial general liability for the individual": [ (("x1", "y1"), ("w1", "h1")), (("x2", "y2"), ("w2", "h2")), (("x3", "y3"), ("w3", "h3")), (("x4", "y4"), ("w4", "h4")), (("x5", "y5"), ("w5", "h5")), (("x6", "y6"), ("w6", "h6")), (("x7", "y7"), ("w7", "h7")), (("x8", "y8"), ("w8", "h8")) ] }
需求是用re.search搜索特定短语(比如commercial general liability),匹配成功后提取该短语及其对应的坐标,存入新字典。期望输出:
op_dict = {'commercial general liability': [(('x3', 'y3'), ('w3', 'h3')), (('x4', 'y4'), ('w4', 'h4')), (('x5', 'y5'), ('w5', 'h5'))]}
用户编写的代码会取出所有坐标,而非目标短语对应的部分:
import re ip_dict = { "Policy general commercial general liability for the individual": [ (("x1", "y1"), ("w1", "h1")), (("x2", "y2"), ("w2", "h2")), (("x3", "y3"), ("w3", "h3")), (("x4", "y4"), ("w4", "h4")), (("x5", "y5"), ("w5", "h5")), (("x6", "y6"), ("w6", "h6")), (("x7", "y7"), ("w7", "h7")), (("x8", "y8"), ("w8", "h8")) ] } op_dict = {} # Search for the key containing "commercial general liability" for key in ip_dict.keys(): if re.search(r"commercial.?\s.?general.?\s.?liability", key, flags = re.DOTALL): op_dict["commercial general liability"] = ip_dict[key] break print(op_dict) # 输出: # {'commercial general liability': [(('x1', 'y1'), ('w1', 'h1')), (('x2', 'y2'), ('w2', 'h2')), (('x3', 'y3'), ('w3', 'h3')), (('x4', 'y4'), ('w4', 'h4')), (('x5', 'y5'), ('w5', 'h5')), (('x6', 'y6'), ('w6', 'h6')), (('x7', 'y7'), ('w7', 'h7')), (('x8', 'y8'), ('w8', 'h8'))]}
问题分析
这段代码只判断了目标短语是否存在,直接把整个坐标列表赋值给新字典,没有定位短语对应的单词在原语句中的位置,自然无法截取对应的坐标片段。
解决方案
核心思路是:先通过正则确认短语存在,再定位短语在原语句单词列表中的位置,最后根据位置截取对应坐标。实现代码如下:
import re ip_dict = { "Policy general commercial general liability for the individual": [ (("x1", "y1"), ("w1", "h1")), (("x2", "y2"), ("w2", "h2")), (("x3", "y3"), ("w3", "h3")), (("x4", "y4"), ("w4", "h4")), (("x5", "y5"), ("w5", "h5")), (("x6", "y6"), ("w6", "h6")), (("x7", "y7"), ("w7", "h7")), (("x8", "y8"), ("w8", "h8")) ] } target_phrase = "commercial general liability" op_dict = {} # 构建正则:转义短语避免语法冲突,允许单词间有任意空白(含换行) pattern = re.compile(re.escape(target_phrase).replace(r'\ ', r'\s+'), flags=re.DOTALL) for key, coords in ip_dict.items(): match = pattern.search(key) if match: # 拆分原语句和目标短语为单词列表 key_words = key.split() phrase_words = target_phrase.split() phrase_len = len(phrase_words) # 遍历找到短语在原单词列表中的起始索引 for i in range(len(key_words) - phrase_len + 1): if key_words[i:i+phrase_len] == phrase_words: # 截取对应坐标并存入新字典 op_dict[target_phrase] = coords[i:i+phrase_len] break break print(op_dict) # 输出: # {'commercial general liability': [(('x3', 'y3'), ('w3', 'h3')), (('x4', 'y4'), ('w4', 'h4')), (('x5', 'y5'), ('w5', 'h5'))]}
代码说明
re.escape(target_phrase):转义短语中的特殊字符,避免和正则语法冲突;后续把转义后的空格替换为\s+,允许单词间有多个空白(包括换行)。- 拆分原语句和目标短语为单词列表,通过遍历对比找到短语在原列表中的起始位置。
- 根据起始索引和短语长度,精准截取对应的坐标片段。
内容的提问来源于stack exchange,提问作者user21785694
相关产品推荐
相关产品推荐

