Python字符串列表和正则表达式列表,干净的方法来查找不匹配的字符串?

时间:2013-07-12 18:29:28

标签: python regex

所以,我有一个正则表达式模式列表和一个字符串列表,我想要做的是在这个字符串列表中说,是否有任何字符串与任何正则表达式都不匹配。

目前,我正在推出正则表达式,以及来自两个词典的正则表达式匹配的值:

我从两个词典中创建了两个列表,一个是模式,一个是键,

patterns = []
keys = []
for pattern, schema in patternproperties.items():
    patterns.append(pattern)
for key, value in value_obj.items():
    keys.append(key)

# Now work out if there are any non-matching keys

for key in keys:
    matches = 0
    for pattern in patterns:
        if re.match(pattern, key):
            matches += 1
    if matches == 0:
        print 'Key %s matches no patterns' %(key)

但这似乎非常低效。任何人都有指向更好的解决方案吗?

3 个答案:

答案 0 :(得分:3)

Regexp针对搜索大块文本而非搜索小块序列进行了优化。因此,您可能需要考虑搜索'\n'.join(keys)而不是单独搜索每个。

或者,或者,不是将循环从Python移动到regexp,而是将隐式的“或”/“任何”位从Python移动到regexp:

pattern = re.compile('|'.join('({})'.format(p) for p in patterns))    
for key in keys:
    if not pattern.match(key):
        print 'Key %s matches no patterns' %(key)

另请注意,我使用了re.compile。这可能没有帮助,因为自动化正则表达式缓存...但它永远不会受到伤害,并且它通常也使代码更容易阅读。


快速timeit测试,简短的键列表和不同数量的简单模式:

patterns   original   alternation
2          76.1 us    42.4 us
3          109 us     42.5 us
4          143 us     43.3 us

所以,我们已经从模式数量的线性变为几乎恒定。

当然,这不会影响更复杂的模式,也不会过多。

答案 1 :(得分:2)

[key for key in keys if not any(re.match(pattern, key) for pattern in patterns)]

答案 2 :(得分:0)

您可以通过多种方式对其进行优化。基本算法是合理的,所以你有一些选择:

  • 如果某些内容匹配,则提前退出循环(而不是计算您不关心的匹配数)。
  • 缓存正则表达式的编译(如果您have a lot of patterns)。
  • 对正则表达式进行排序,以便快速匹配的正则表达式首先出现。通过这种方式,您的提前终止将获得最大的收益。
  • 使用列表推导,这可能比手动迭代更快(可能有一天允许Python解释器并行化,尽管今天可​​能没有)。虽然阅读并不一定容易。 (有关某些意见,请参阅is it better to use list comprehensions or for each loops。)

不同的算法可能是首先在模式上进行迭代,并在一个模式匹配时从潜在密钥集中删除内容。类似的东西:

remainder = set(keys)
for pattern in patterns:
    toremove = set()
    for key in remainder:
        if re.match(pattern, key):
            toremove.add(key)
    remainder -= toremove
如果您的模式与许多键匹配,那么

可能会有所帮助。

您当然应该衡量您的情况和输入,以确定哪种优化最合适。