【问题标题】:Regex match number, a multiple of 5, between 1 to 1000 inclusive正则表达式匹配数,5 的倍数,介于 1 到 1000(含)之间
【发布时间】:2021-10-13 16:02:42
【问题描述】:

我一直面临这个我无法解决的问题。

compiler = re.compile(r'\d*[05]')
result = compiler.findall('0 20 201 95 5 52 35 999 40 19 50 1000 245 1050 118 2500')

期望的输出: ['20', '95', '5', '35', '40', '50', '1000', '245']

根据我上面的代码,我可以达到的最接近: ['0', '20', '20', '95', '5', '5', '35', '40', '50', '1000', '245', '1050', '2500']

我应该只在代码re.compile(r'--------') 的虚线部分提供我的答案。

如果有人可以帮助我,那就太好了,谢谢。

【问题讨论】:

  • 是否需要使用正则表达式来完成?不是真正适合这项工作的工具。
  • 不幸的是,问题的要求是只使用正则表达式..

标签: python regex python-re


【解决方案1】:

使用regex pattern、\b(?!0)(?:\d{0,2}[05]\b|1000)\b可以满足要求。

演示:

import re

compiler = re.compile(r'\b(?!0)(?:\d{0,2}[05]\b|1000)\b')
result = compiler.findall('0 20 201 95 5 52 35 999 40 19 50 1000 245 1050 118 2500')
print(result)

输出:

['20', '95', '5', '35', '40', '50', '1000', '245']

正则表达式的解释:

  • \b : 字边界
  • (?!0) :负前瞻断言不应该有 0 在当前位置之前。
  • (?: : 非捕获组的开始
    • \d{0,2} :一个数字,零到两次
    • [05] : 0 或 5
    • \b:字边界
    • |1000:或 1000
  • ) : 非捕获组结束
  • \b:字边界

根据The fourth bird 的以下宝贵建议更新:

为防止部分匹配 1000,您可以从单词开始 边界,断言不为零并将整个交替包装在 非捕获组,再次以单词边界结尾 \b(?!0)(?:\d{0,2}[05]\b|1000)\b

【讨论】:

    【解决方案2】:

    正如@depperm 指出的那样

    \b(?!\b0\b)(\d{0,2}[05]|1000)\b
    

    将是满足您需求的完美正则表达式。

    我的想法只适用于单个数字

    ^\d{0,2}[05]$|^1000$
    

    解释:

    • ^ 表明,字符串必须从这里开始
    • /d{0,2} 代表 0,1 或 2 个数字
    • [05] 数字 0 或 5,因为 5 的所有倍数都以 0 或 5 结尾
    • $ 字符串结束
    • | 代表操作员或
    • ^1000$ 代表字符串 1000

    但正如已经指出的那样,您也可以查看其他方式

    【讨论】:

    • 我相信需要\b(?!\b0\b)(\d{0,2}[05]|1000)\b 才能获得所有结果
    • @depperm 你有没有我的表达找不到的号码?我以为我把它们都藏起来了
    • 提供的输入(单个字符串中的所有数字)我相信您需要类似\b 而不是^..$
    • 见code
    • 是的,你是对的,我错过了用例,你的表达方式很优越
    【解决方案3】:

    您不需要为此使用正则表达式。您可以使用理解:

    result = [i for i in data.split() if not (n := int(i)) % 5 and n <= 1000 and n]
    

    这相当于:

    result = []
    for i in data.split():
        n = int(i)
        if not n % 5 and n <= 1000 and n:
            result.append(i)
    

    【讨论】:

    • 不幸的是,问题的要求是使用正则表达式,但不胜感激!
    【解决方案4】:

    当所有内容都在一个字符串中时,我们需要为搜索添加边界。另一个答案很接近,但是当单个字符串包含多个值时,我们无法通过 ^ 和 $ 进行匹配。

    \b 或单词边界确保在匹配字符串之前或之后没有额外的数字。

    模式:\b0\b|(\b\d{0,2}[05]\b|\b1000\b)

    所有想要的匹配都在第 1 组中

    https://regex101.com/r/Efhcsb/2

    【讨论】:

    • 不应捕获 0
    • 不应捕获 0
    • 是的,通过将所有内容放在第 1 组中,我们可以将 \b0\b 从我们的解决方案集中排除。
    • 在python中返回['', '20', '95', '5', '35', '40', '50', '1000', '245']
    【解决方案5】:

    您可以使用 5 到 1000 之间的标准数字范围生成器来获取
    [5-9]|[1-9]\d|[1-9]\d{2}|1000

    然后将最后一位数字替换为“[05]”得到5|[1-9][05]|[1-9]\d[05]|1000。

    重构它并添加单词边界的'\b'以获得\b(?:5|[1-9]\d?[05]|1000)\b

    Python 测试:

    >>> import re
    >>> Rx = re.compile(r'\b(?:5|[1-9]\d?[05]|1000)\b')
    >>> Rx.findall('0 20 201 95 5 52 35 999 40 19 50 1000 245 1050 118 2500')
    ['20', '95', '5', '35', '40', '50', '1000', '245']
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-27
      • 1970-01-01
      • 2019-03-11
      • 2018-08-27
      相关资源
      最近更新 更多