正则表达式匹配数


72

我正在使用模块中的finditer函数re来匹配某些东西,并且一切正常。

现在,我需要找出我有多少场比赛。是否可以不两次遍历迭代器?(先找出计数然后是真正的迭代)

一些代码:

imageMatches = re.finditer("<img src\=\"(?P<path>[-/\w\.]+)\"", response[2])
# <Here I need to get the number of matches>
for imageMatch in imageMatches:
    doStuff

一切正常,我只需要在循环之前获取匹配数即可。

Answers:


102

如果您知道需要所有匹配项,则可以使用该re.findall功能。它将返回所有匹配项的列表。然后,您可以只进行len(result)匹配次数。


8
@Rafe Kettler:findall发现不重叠。从文档中:以字符串列表的形式返回字符串中模式的所有非重叠匹配。从左到右扫描字符串,并以找到的顺序返回匹配项。
JoshD 2010年

@Rafe Kettler&JoshD:感谢您的澄清,这些部分永远不会重叠,因此在这种情况下对我来说不会有问题。re.findall的唯一烦人之处是我失去了我的命名组,但它可以正常工作,因此就足够了。
dutt 2010年

好吧,我还是贴出了答案。快乐的足迹。
拉菲·凯特勒

2
len(re.findall(pattern, string))
Campos

10

如果您始终需要知道长度,并且只需要匹配的内容而不是其他信息,则可以使用re.findall。否则,如果有时仅需要长度,则可以使用例如

matches = re.finditer(...)
...
matches = tuple(matches)

将匹配的迭代存储在可重用的元组中。然后就做len(matches)

如果您只需要在对匹配对象执行任何操作之后就知道总数,那么另一种选择是使用

matches = enumerate(re.finditer(...))

它将(index, match)为每个原始匹配返回一对。因此,您只需将每个元组的第一个元素存储在某个变量中即可。

但是,如果您首先需要长度,并且需要匹配对象而不是字符串,则应该这样做

matches = tuple(re.finditer(...))

6

如果您发现需要坚持 finditer(),则可以在遍历迭代器时简单地使用一个计数器。

例:

>>> from re import *
>>> pattern = compile(r'.ython')
>>> string = 'i like python jython and dython (whatever that is)'
>>> iterator = finditer(pattern, string)
>>> count = 0
>>> for match in iterator:
        count +=1
>>> count
3

如果您需要的功能finditer()(不匹配重叠的实例),请使用此方法。


是的,我曾考虑过这样做,但是由于我的“ doStuff”代码中的内容,如果不在各个地方添加很多额外的代码,这些代码将无法正常工作。无论如何,谢谢小费:)
dutt 2010年

我会用for count, match in enumerate(iterator):Rafe的代码。
Tony Veijalainen 2010年

@Tony:谢谢,忘了列举。但是,如果您确实使用枚举,它将为您提供最高的索引,而不是实际的匹配数;对于这一点,你就必须加1
雷夫凯特勒

for count, match in enumerate(iterator)在没有匹配项的地方严重退步。count = -1在循环之前添加可能是一个可接受的解决方案。
janislaw 2011年

6
#An example for counting matched groups
import re

pattern = re.compile(r'(\w+).(\d+).(\w+).(\w+)', re.IGNORECASE)
search_str = "My 11 Char String"

res = re.match(pattern, search_str)
print(len(res.groups())) # len = 4  
print (res.group(1) ) #My
print (res.group(2) ) #11
print (res.group(3) ) #Char
print (res.group(4) ) #String

1
我认为len(res.groups())重新匹配什么都不会引发异常
pbaranski

2

我知道这有点旧,但这是一个用于计数正则表达式模式的简洁函数。

def regex_cnt(string, pattern):
    return len(re.findall(pattern, string))

string = 'abc123'

regex_cnt(string, '[0-9]')

0

对于那些您确实要避免生成列表的时刻:

import re
import operator
from functools import reduce
count = reduce(operator.add, (1 for _ in re.finditer(my_pattern, my_string))) 

有时您可能需要对巨大的字符串进行操作。这可能会有所帮助。


3
我建议:sum(1 for _ in re.finditer(my_pattern, my_string))不用了,减少复杂性和operation.add
d哈德森
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.