例如,我有单词列表形式的句子
sentence = ['if', 'it', 'will', 'rain', ',', 'I', 'will', 'stay', 'at', 'home']
现在我想找到条件子句 ['if', 'it', 'will', 'rain']。原则上,我可以从句子中创建一个字符串,例如s = ' '.join(sentence),我和使用正则表达式:
p = re.compile(r'(\bif\b[a-zA-z0-9\'\s]+)\s*(,*)\s*(then|,)')
for m in p.finditer(s):
print m.start(1), m.end(1), '['+s[ m.start(1) : m.end(1) ]+']'
无需判断正则表达式,它只是一个快速草图 :)。这给了我输出:0 16 [if it will rain]
到目前为止一切顺利。但现在我有点想念与原始列表的联系。正则表达式给我字符位置而不是单词/标记位置。理想情况下,我会得到 0 和 3,这样我就知道条件从句是 sentence[0:3]。我确定我可以编写一个将字符位置映射到相应列表索引的方法,但我确定还有更好的方法来完成这一切。
当然,我可以忽略正则表达式,遍历列表并提出正确的开始和停止条件。但常规目前看起来相当整洁,因为它们“隐藏”以使所需条件明确。它们还简化了条件从句由其他单词或短语表示的情况,例如:
sentence = ['as', 'long', 'as', 'it', 'will', 'rain', ',', 'I', 'will', 'stay', 'at', 'home']
用正则表达式很容易反射(reflect)这一点,我想使用循环会有点烦人。
编辑:看到实际上并没有一个非常简单的解决方案,我继续我的想法,即在作为正则表达式字符串的句子和原始单词列表之间创建一个映射:
def join(self, word_list, separator=' '):
mapping = []
string = separator.join(word_list)
for idx, word in enumerate(word_list):
for character in word:
mapping.append(idx)
for character in separator:
mapping.append(idx)
return string, mapping
将此方法应用于我的输入 string, mapping = join(sentence) 结果:
mapping = [0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9]
现在,如果正则表达式给我 0 和 16 作为匹配范围,我可以在原始 句子 中查找索引mapping[0] = 0 和 mapping[16] = 4 列表。到目前为止,这似乎工作得相当好。由于我使用字符串的正则表达式进行匹配,因此我可以轻松支持条件子句的替代公式,例如:
CONDITIONAL_PHRASES = ['if', 'as long as', 'even if']
...
p = re.compile(r"((%s)\s+[a-zA-z0-9'\s]+)\s*(then|,)" % '|'.join(CONDITIONAL_PHRASES))
再说一遍,我并不是说正则表达式已经很完美了,但它同时支持多个句子,条件从句有不同的指示词。
请您参考如下方法:
注意:-如果if和只出现一次,或中的then句子
我稍微修改了你的正则表达式以包含一个捕获组
re.compile("((\\bif\\b)[a-zA-z0-9\\'\\s]+)\\s*(,*)\\s*(then|,)")
你可以使用 re.findall 作为
arr = re.findall(p, s)
arr[0][1] 包含第一个捕获组(字符串 if)并且 arr[0][3] 包含第三个捕获组(字符串 then 或 ,)。您可以使用索引来查找这 2 个的索引作为
start = sentence.index(arr[0][1])
end = sentence.index(arr[0][3])
现在,您可以使用
stri = ' '.join(sentence[start: end])
注意 1:- 如果 if 和 出现不止一次, 或 then 在 句子(非重叠),你将不得不遍历所有元组
arr = re.findall(p, s)
pos = 0 #It stores the last occurrence of matched group
for i, x in enumerate(arr):
start = sentence.index(x[1], pos)
end = sentence.index(x[3], pos)
stri = ' '.join(sentence[start: end])
print(stri)
pos = sentence.index(x[3], pos) + 1
注意 2:- 请记住,如果未找到字符串,index 会引发异常。在做上面之前处理一下
