【问题标题】:Finding a simpler Python RegEx for a string that contains each character at least once为包含每个字符至少一次的字符串查找更简单的 Python RegEx
【发布时间】:2017-05-24 20:16:29
【问题描述】:

我正在做一个小项目,需要正则表达式来接受包含给定字母表中每个字符的字符串至少一次

所以对于字母表{J, K, L},我需要一个正则表达式,它接受包含J 一次或多次和K 一次或多次,以及L 一次或多次的字符串,以任意顺序,任意之前、之后或中间的重复字符数量。

我对 RegEx 非常缺乏经验,因此很难找到许多问题的“横向思维”解决方案。因此,我的第一种方法是相当蛮力的:我采用了每个可能的“基本”字符串,例如,

JKL, JLK, KJL, KLJ, LKJ, LJK

并允许任何可以从这些起点之一建立的字符串。然而,生成的正则表达式*(尽管可以工作)最终会很长并且包含很多冗余。更不用说,一旦字母表包含多个字符,这种方法就变得完全站不住脚了。

我花了几个小时试图找到一种更优雅的方法,但我还没有找到一种仍然接受所有可能字符串的方法。有没有一种方法或技术可以让我以更优雅和可扩展的方式完成这项工作(适用于更大的字母表)?

*作为参考,我列出示例的正则表达式:

((J|K|L)*J(J|K|L)*K(J|K|L)*L(J|K|L)*)|
((J|K|L)*J(J|K|L)*L(J|K|L)*K(J|K|L)*)|
((J|K|L)*K(J|K|L)*J(J|K|L)*L(J|K|L)*)|
((J|K|L)*K(J|K|L)*L(J|K|L)*J(J|K|L)*)|
((J|K|L)*L(J|K|L)*J(J|K|L)*K(J|K|L)*)|
((J|K|L)*L(J|K|L)*K(J|K|L)*J(J|K|L)*)

【问题讨论】:

  • 你能发布无效输入的例子吗?
  • @RomanPerekhrest 对于列出的示例,任何不包含至少一个 J、K 和 L 的字符串。因此,“JK”、“KLLKK”和“JJLLLJL”都会被拒绝。
  • 前瞻正则表达式答案可能比使用字符串查找函数为每个数组字符循环要慢。它们都做同样的事情(即从字符串开头开始),但是正则表达式有一些开销状态(如断言组和否定类)会使其变慢。
  • @sln 感谢您的提示。这个项目主要是为了试验 RegEx,但我以后会记住这一点。
  • 如果您只是想弄乱正则表达式并寻找与断言不同的方法,请使用新的 regex 模块并在其上尝试(?:.*?(?:((?(1)(?!))j)|((?(2)(?!))k)|((?(3)(?!))l))){3} 因为断言不是他们真的在试验吗?尝试和benchmark 实验,你可能会对你的发现感到惊讶。

标签: python regex


【解决方案1】:

这是前瞻的典型用例。您可以简单地使用^(?=[^J]*J)(?=[^K]*K)(?=[^L]*L) 来检查您的所有条件。如果您的字符串也必须只包含这些字符,您可以将[JKL]+$ 附加到它。

【讨论】:

  • 完美。我以前见过前瞻性,但在思考问题时它不在我的“心理工具箱”中。
【解决方案2】:

如果不需要使用正则表达式,您也可以单独检查字符:

text = ...
alphabet = 'JKL'
assert all([character in text for character in alphabet])

或者,如果您不想允许不在字母表中的字符:

assert set(alphabet) == set(text)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-10
    • 1970-01-01
    • 2012-06-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多