首页 > 解决方案 > 具有不同字符数的正则表达式

问题描述

我需要创建一个正则表达式来验证字符串。字符串只能有几个字符,每个字符只能重复几次。

正则表达式应检查以下条件。

  1. 字符串只能包含a、b、c、d、e作为字符。
  2. 字符“ a ”最多可出现 2 次。
  3. 字符“ b ”最多可出现 3 次。
  4. 字符“ c ”最多可出现 3 次。
  5. 字符 ' d ' 最多可以出现 1 次。
  6. 字符' e '最多可以出现1次。

我知道这可以通过字符串函数来实现。但我正在尝试用正则表达式来做到这一点。

对此的任何帮助都将受到高度赞赏。

标签: pythonregex

解决方案


可能,性能方面,最好的方法是使用 Python 原生字符串操作。

我会这样写:

lim=(('a',2),('b',3),('c',3),('d',1),('e',1))
results={}
for s in [list_of_many_strings]:
    results[s]=bool(not(set(s)-set('abcde'))) and (not any(s.count(c)>x for c,x in lim))

这依赖于str.count(sub[, start[, end]])来计算字符串中子字符串的出现次数以及任何函数来测试任何条件是否为真。


由于您对性能感兴趣,您可以计算处理 100,000 个字符串可能需要多长时间timeit

import re

def f1(li):
    results={}
    lim=(('a',2),('b',3),('c',3),('d',1),('e',1))
    for s in li:
        results[s]=bool(not(set(s)-set('abcde'))) and (not any(s.count(c)>x for c,x in lim))

    return results    

def f2(li):
    pat=re.compile(r'^a{0,2}b{0,3}c{0,3}d{0,1}e{0,1}$')
    results={}
    for s in li:
        results[s]=True if pat.search(''.join(sorted(s))) else False

    return results

def f3(li):
    pat=re.compile(r'^(?!.*[^a-e])(?!(?:.*a){3})(?!(?:.*b){4})(?!(?:.*c){4})(?!(?:.*d){2})(?!(?:.*e){2}).+')
    results={}
    for s in li:
        results[s]=True if pat.search(s) else False    

    return results    

if __name__=='__main__':
    import timeit    
    import random 
    s='abcdeabcdebc'
    li=[''.join(random.sample(s,8)) for _ in range(100000)]
    print(f1(li)==f2(li)==f3(li))

    for f in (f1,f2,f3):
        print("   {:^10s}{:.4f} secs".format(f.__name__, timeit.timeit("f(li)", setup="from __main__ import f, li", number=10)))

在我的电脑上,需要:

True
       f1    0.8519 secs
       f2    1.1235 secs
       f3    1.3070 secs

推荐阅读