对于非重叠匹配,基于findall
的现有解决方案很好(除了可能在匹配数量巨大时不是最优的)。如果您只关心计数而不使用列表,则可以使用其他选择,例如:sum(1 for m in re.finditer(thepattern, thestring))
。使用subn
并忽略结果字符串会有点特殊...:
def countnonoverlappingrematches(pattern, thestring):
return re.subn(pattern, '', thestring)[1]
如果你只想计算(比如说)前100个匹配的话,那么后一种方法的唯一优势就在于这种情况下使用re.subn(pattern, '', thestring, 100)[1]
可能更实用(无论有100次匹配还是1000次、甚至更多次都返回100)。
计算重叠的匹配需要你编写更多代码,因为相关的内置函数都专注于非重叠匹配。还有一个定义问题,例如如果pattern是'a+'
,thestring是'aa'
,你会认为这是一个匹配、三个匹配(第一个a
,第二个a
,或者都包含),还是其他什么?
假设你想要的是可能重叠的匹配,而且它们必须从字符串中不同的位置开始(这样对于前面那个例子会得到两个匹配):
def countoverlappingdistinct(pattern, thestring):
total = 0
start = 0
there = re.compile(pattern)
while True:
mo = there.search(thestring, start)
if mo is None: return total
total += 1
start = 1 + mo.start()
请注意,在这种情况下,您必须将模式编译为RE对象:函数
re.search
不接受
start
参数(搜索的起始位置),就像
方法search
一样。因此,您必须在进行搜索时对字符串进行切片——这肯定比让下一个搜索从下一个可能的不同起始点开始更费力,而这正是我在此函数中所做的。