【问题标题】:Matching unique groups while maintaining their order匹配独特的群体,同时保持他们的秩序
【发布时间】:2017-08-31 23:09:03
【问题描述】:

有没有办法完全在正则表达式中按出现顺序匹配唯一的字符组(以下情况下的单词)?如果是这样,该表达式在效率上与非正则表达式解决方案相比如何?我正在使用 Python 的风格,但我也对任何其他风格的解决方案感兴趣。

这是一个示例案例:

string = 'the floodwaters are rising along the coast'
unique = ['the', 'floadwaters', 'are', 'rising', 'along', 'coast']

在 Python-regex 混合解决方案中,我可以匹配我想要的组,并使用列表推导来删除重复项,同时保持顺序。

groups = re.findall('[a-zA-Z]+', string)
unique = [g for i, g in enumerate(groups) if g not in groups[:i]]

整个网站都有类似的问题,例如one that addresses matching unique words。然而,接受答案的表达式匹配给定组的最右边出现,而我想匹配 first 出现。这是那个表达式:

(\w+\b)(?!.*\1\b)

【问题讨论】:

  • 正则表达式库不同。在 Python 中,您可以使用 PyPi regex 库,并使用 \b(\w+)\b(?<!(?:.*\b\1\b){2})。在 .NET 中,您也可以使用它。
  • 通常,例如 C++ 中的 unique,不保留顺序。那是因为必须先对列表进行排序。
  • (\w+\b)(?!.*\1\b) 不会匹配第一次出现的单词。它将匹配最后的副本,而不是开始。您最好的选择是拆分以获取所有单词,然后从该集合中进行 unique 进行自己的保存。正则表达式会慢得令人难以置信www........
  • @WiktorStribiżew:确实可以与regex 库一起使用(感谢快速建议),但我正在寻找广泛(最好是本地)兼容的东西。除了你链接的那个之外,我似乎也无法让它与任何在线正则表达式测试器一起工作。
  • 没有“本机兼容”正则表达式。正如我所说,所有正则表达式的风格都是不同的。在绝大多数情况下,您无法单独使用正则表达式完成您需要的工作。

标签: regex performance regex-group


【解决方案1】:

这种任务的纯正则表达式解决方案只能通过 infinite-width 后视来实现。

然而,像这样的正则表达式解决方案应该在输入相对较短的情况下考虑使用:输入字符串中超过 100 个单词会使其非常慢由于在这种情况下是不可避免的回溯。因此,仅出于学习目的,我将分享仅在 .NET 和 Python PyPi regex 库中支持的正则表达式(在 Vim 中也可以这样做,因为它的后视也是无限的——宽度,但我想这个强大的工具还有更简单的方法)。

(?s)\b(\w+)\b(?<!^.*\b\1\b.*\b\1\b)

regex demo

(?s) 部分是一个内联修饰符,它使. 匹配所有换行符。你可以在 Python 中使用regex.DOTALL regex

详情

  • \b - 初始单词边界
  • (\w+) - 第 1 组:一个或多个单词字符
  • \b - 词尾边界
  • (?&lt;!^.*\b\1\b.*\b\1\b) - 如果匹配到第 1 组的单词恰好出现在其自身之前至少一次,即如果紧邻当前位置的左侧(即在捕获的单词之后),则无限宽度的负向后查找失败,有一系列模式:
    • ^ - 字符串开头
    • .*\b\1\b - 任何零个或多个字符,尽可能多,然后与第 1 组中的值相同
    • .*\b\1\b - 与上面相同(需要匹配捕获的单词,因为在使用的单词之后使用了lookbehind)

lookbehind 中的 .* 会导致大量回溯,并且该模式通常会运行得很慢,并且在输入大量时会非常缓慢,最终可能会导致超时。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-22
    • 2017-12-23
    • 1970-01-01
    • 2017-05-29
    • 2018-04-17
    • 2014-02-26
    • 2018-11-08
    相关资源
    最近更新 更多