我有一个文本,其中的单词由.
分隔,带有 2 个和 3 个连续重复单词的实例:
我。name.name是。Inigo.Montoya.You.killed.my。父亲.父亲.父亲。Prepare.to.die-
我需要将它们与正则表达式独立匹配,从一式三份中排除重复项。
由于最多有 3 个连续重复的单词,因此这
r'b(w+).+1.+1b'
成功抓住
父亲.父亲.父亲
但是,为了捕捉 2 个连续重复的单词,我需要确保下一个和上一个单词不同。我可以做一个消极的展望
r'b(w+).+1(?!.+1)b'
但我对负面回头的尝试
r'(?<!(w).)b1.+1b(?!.1)'
要么返回固定宽度的问题(当我保留+
时(或其他一些问题。
我应该如何纠正负面的滞后?
我认为可能有一种更简单的方法可以捕获您想要的内容,而无需负面的回溯:
r = re.compile(r'b((w+).+2.+2?)b')
r.findall(t)
> [('name.name.', 'name'), ('father.father.father', 'father')]
只是使第三次重复可选。
捕获同一单词的任意重复次数的版本可能如下所示:
r = re.compile(r'b((w+)(.+2)3*)b')
r.findall(t)
> [('name.name', 'name', '.name'), ('father.father.father', 'father', '.father')]
也许根本不需要正则表达式。
使用itertools.groupby
可以完成这项工作。它旨在对连续项的相等匹配项进行分组。
- 按单词分组(根据点拆分后(
- 转换为列表并发出
tuple
值,仅当长度> 1 时才计数
喜欢这个:
import itertools
s = "My.name.name.is.Inigo.Montoya.You.killed.my.father.father.father.Prepare.to.die"
matches = [(l[0],len(l)) for l in (list(v) for k,v in itertools.groupby(s.split("."))) if len(l)>1]
结果:
[('name', 2), ('father', 3)]
所以基本上我们可以对这个元组列表做任何我们想做的事情(例如,根据出现次数过滤它(
奖金(因为我一开始误读了这个问题,所以我把它留在了里面(:从句子中删除重复项 - 按单词分组(根据点拆分后(,如上 - 只取列表 comp 中返回的值的键(值((我们不需要这些值,因为我们不计数( - 用点连接回来
在一行中(仍在使用itertools
(:
new_s = ".".join([k for k,_ in itertools.groupby(s.split("."))])
结果:
My.name.is.Inigo.Montoya.You.killed.my.father.Prepare.to.die