sirve - Averigüe cuántas veces coincide una expresión regular en una cadena en Python
python string expresiones regulares (7)
¿Hay alguna forma de averiguar cuántas coincidencias de expresiones regulares hay en una cadena en Python? Por ejemplo, si tengo la cadena "It actually happened when it acted out of turn."
Quiero saber cuántas veces aparece "ta"
en la cadena. En esa cadena, "ta"
aparece dos veces. Quiero que mi función me diga que apareció dos veces. es posible?
¿Has probado esto?
len( pattern.findall(source) )
Las soluciones existentes basadas en findall
están bien para coincidencias no superpuestas (y sin duda óptimas, excepto tal vez para una GRAN cantidad de coincidencias), aunque alternativas como la sum(1 for m in re.finditer(thepattern, thestring))
(para evitar siempre materializar la lista cuando lo único que importa es el conteo) también son bastante posibles. Algo idiosincrásico estaría usando subn
e ignorando la cadena resultante ...:
def countnonoverlappingrematches(pattern, thestring):
return re.subn(pattern, '''', thestring)[1]
la única ventaja real de esta última idea vendría si solo te importara contar (por ejemplo) hasta 100 coincidencias; entonces, re.subn(pattern, '''', thestring, 100)[1]
puede ser práctico (devuelve 100 si hay 100 coincidencias, o 1000, o incluso números más grandes).
El conteo de coincidencias superpuestas requiere que escriba más código, ya que las funciones integradas en cuestión se centran en coincidencias que NO se superponen. También hay un problema de definición, por ejemplo, si el patrón es ''a+''
y la cadena es ''aa''
, consideraría que esto es solo una coincidencia, o tres (la primera a
, la segunda, ambas), o. ..?
Suponiendo, por ejemplo, que desea coincidencias que posiblemente se superpongan comenzando en distintos puntos de la cadena (que luego daría DOS coincidencias para el ejemplo en el párrafo anterior):
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()
Tenga en cuenta que tiene que compilar el patrón en un objeto RE en este caso: la función re.search
no acepta un argumento de start
(posición de inicio para la búsqueda) de la forma en que lo hace la search
métodos , por lo que tendría que dividir la estructura como vaya, definitivamente más esfuerzo que el inicio de la próxima búsqueda en el siguiente punto de inicio posible, que es lo que estoy haciendo en esta función.
Para evitar la creación de una lista de coincidencias, también se puede usar re.sub con un invocable como reemplazo. Se invocará en cada partido, incrementando el contador interno.
class Counter(object):
def __init__(self):
self.matched = 0
def __call__(self, matchobj):
self.matched += 1
counter = Counter()
re.sub(some_pattern, counter, text)
print counter.matched
Puede encontrar coincidencias superpuestas utilizando un subpatrón no de captura:
def count_overlapping(pattern, string):
return len(re.findall("(?=%s)" % pattern, string))
Sé que esta es una pregunta sobre expresiones regulares. Simplemente pensé que mencionaría el método de count para futuras referencias si alguien quiere una solución no regex.
>>> s = "It actually happened when it acted out of turn."
>>> s.count(''t a'')
2
Que devuelven el número de apariciones no superpuestas de la subcadena
import re
len(re.findall(pattern, string_to_search))
import re
print len(re.findall(r''ab'',u''ababababa''))