我不确定正则表达式是最好的方法,但它似乎非常适合。基本上我目前正在使用pdfminer解析一些pdf,缺点是这些pdf是导出的powerpoint幻灯片,这意味着所有动画都显示为相当长的字符串副本。理想情况下,我希望每个字符串只有一个副本,而不是动画的每个阶段的副本。现在我正在使用的当前正则表达式是:
re.sub(r"([\w^\w]{10,})\1{1,}", "\1", string)
出于某种原因,这似乎并没有改变输入字符串。我觉得由于某种原因python没有认识到捕获组,但我不确定如何解决这个问题。任何想法都赞赏。
示例:
I would like this
text to be
reduced
I would like this
text to be
reduced
输出:
I would like this
text to be
reduced
更新: 为了让这个通过pumping lemma我必须专门断言所有重复都是相邻的。这是之前暗示的,但我现在明确表示可以确保解决方案成为可能。
答案 0 :(得分:2)
regexp不是该任务的正确工具。它们基于context free languages的理论,如果字符串包含重复项并删除重复项,则它们无法匹配。您可以在automata和regexps上找到有关该主题的有趣课程。
我认为Josay的建议可以高效而聪明,但我认为我有一个更简单和pythonic的解决方案,尽管它有其局限性。您可以将字符串拆分为行列表,并将其传递给set()
:
>>> s = """I would like this
... text to be
...
... reduced
... I would like this
... text to be
...
... reduced"""
>>> print "\n".join(set(s.splitlines()))
I would like this
text to be
reduced
>>>
该解决方案唯一的解决方案是你将松开线条的原始顺序(这个例子是一个很好的反例)。此外,如果在两个不同的上下文中有相同的行,则最终只有一行。
否则将需要更复杂的算法,因此您可以考虑邻近度和上下文。为此,后缀树可能是一个好主意,并且有python库(cf that SO answer)。
编辑:
使用您的算法我可以通过添加多行支持并在文本匹配中添加空格和结束来使其工作:
>>> re.match(r"([\w \n]+)\n\1", string, re.MULTILINE).groups()
('I would like this\ntext to be\n\nreduced',)
尽管如此,\1
表示法不是匹配部分中的常规正则表达式语法,而是扩展名。但是现在已经很晚了,我可能完全错了。也许我会重读那些课程? : - )
我认为regexp引擎的下推自动机能够推送匹配,因为它只是一个很长的多行字符串,它可以弹出来匹配。虽然我希望它有副作用......