我的文字包含.
分隔的单词,其中包含2个和3个连续重复单词的实例:
My.name.name.is.Inigo.Montoya.You.killed.my.father.father.father.Prepare.to.die-
我需要将它们与正则表达式独立匹配,不包括重复的重复项。
因为有最大值连续3个重复的单词,这个
r'\b(\w+)\.+\1\.+\1\b'
成功捕获
father.father.father
但是,为了捕获连续2个重复的单词,我需要确保下一个和前一个单词不相同。我可以做一个负面预测
r'\b(\w+)\.+\1(?!\.+\1)\b'
但是我尝试了负面观察
r'(?<!(\w)\.)\b\1\.+\1\b(?!\.\1)'
要么返回固定宽度问题(当我保留+
时),要么返回其他问题。
我应该如何纠正负面观察?
答案 0 :(得分:3)
我认为可能有一种更简单的方法来捕捉你想要的东西,而没有负面的背后隐藏:
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')]
答案 1 :(得分:3)
根本不需要正则表达式。
使用itertools.groupby
完成这项工作。
tuple
值,仅在长度&gt;时计数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