Encuentra todas las apariciones de una subcadena en Python

Python tiene string.find() y string.rfind() para obtener el índice de una subcadena en string.

Me pregunto, tal vez hay algo como string.find_all() que puede devolver todos los índices fundados (no solo el primero desde el principio o el primero desde el final).

Por ejemplo:

 string = "test test test test" print string.find('test') # 0 print string.rfind('test') # 15 #that's the goal print string.find_all('test') # [0,5,10,15] 

No hay una simple función de cadena incorporada que haga lo que estás buscando, pero podrías usar las expresiones regulares más poderosas:

 import re [m.start() for m in re.finditer('test', 'test test test test')] #[0, 5, 10, 15] 

Si desea encontrar coincidencias superpuestas, lookahead lo hará:

 [m.start() for m in re.finditer('(?=tt)', 'ttt')] #[0, 1] 

Si desea una búsqueda inversa de todo sin superposiciones, puede combinar lookahead positivo y negativo en una expresión como esta:

 search = 'tt' [m.start() for m in re.finditer('(?=%s)(?!.{1,%d}%s)' % (search, len(search)-1, search), 'ttt')] #[1] 

re.finditer devuelve un generador , por lo que podría cambiar el [] de lo anterior a () para obtener un generador en lugar de una lista que será más eficiente si solo está iterando a través de los resultados una vez.

 >>> help(str.find) Help on method_descriptor: find(...) S.find(sub [,start [,end]]) -> int 

Así, podemos construirlo nosotros mismos:

 def find_all(a_str, sub): start = 0 while True: start = a_str.find(sub, start) if start == -1: return yield start start += len(sub) # use start += 1 to find overlapping matches list(find_all('spam spam spam spam', 'spam')) # [0, 5, 10, 15] 

No se requieren cadenas temporales o expresiones regulares.

Aquí hay una forma (muy ineficiente) de obtener todas las coincidencias (es decir, incluso superpuestas):

 >>> string = "test test test test" >>> [i for i in range(len(string)) if string.startswith('test', i)] [0, 5, 10, 15] 

Nuevamente, hilo viejo, pero aquí está mi solución usando un generador y un str.find simple.

 def findall(p, s): '''Yields all the positions of the pattern p in the string s.''' i = s.find(p) while i != -1: yield i i = s.find(p, i+1) 

Ejemplo

 x = 'banananassantana' [(i, x[i:i+2]) for i in findall('na', x)] 

devoluciones

 [(2, 'na'), (4, 'na'), (6, 'na'), (14, 'na')] 

Puede usar re.finditer() para coincidencias que no se superponen.

 >>> import re >>> aString = 'this is a string where the substring "is" is repeated several times' >>> print [(a.start(), a.end()) for a in list(re.finditer('is', aString))] [(2, 4), (5, 7), (38, 40), (42, 44)] 

pero no funcionará para:

 In [1]: aString="ababa" In [2]: print [(a.start(), a.end()) for a in list(re.finditer('aba', aString))] Output: [(0, 3)] 

Ven, vamos a hacer juntos la terapia.

 def locations_of_substring(string, substring): """Return a list of locations of a substring.""" substring_length = len(substring) def recurse(locations_found, start): location = string.find(substring, start) if location != -1: return recurse(locations_found + [location], location+substring_length) else: return locations_found return recurse([], 0) print(locations_of_substring('this is a test for finding this and this', 'this')) # prints [0, 27, 36] 

No hay necesidad de expresiones regulares de esta manera.

Si solo estás buscando un solo personaje, esto funcionaría:

 string = "dooobiedoobiedoobie" match = 'o' reduce(lambda count, char: count + 1 if char == match else count, string, 0) # produces 7 

También,

 string = "test test test test" match = "test" len(string.split(match)) - 1 # produces 4 

Mi corazonada es que ninguno de estos (especialmente el # 2) es terriblemente eficaz.

este es un hilo antiguo, pero me interesé y quería compartir mi solución.

 def find_all(a_string, sub): result = [] k = 0 while k < len(a_string): k = a_string.find(sub, k) if k == -1: return result else: result.append(k) k += 1 #change to k += len(sub) to not search overlapping results return result 

Debe devolver una lista de posiciones donde se encontró la subcadena. Por favor comente si ve un error o espacio para mejorar.

Este hilo es un poco viejo pero esto funcionó para mí:

 numberString = "onetwothreefourfivesixseveneightninefiveten" testString = "five" marker = 0 while marker < len(numberString): try: print(numberString.index("five",marker)) marker = numberString.index("five", marker) + 1 except ValueError: print("String not found") marker = len(numberString) 

Esto hace el truco para mí usando re.finditer

 import re text = 'This is sample text to test if this pythonic '\ 'program can serve as an indexing platform for '\ 'finding words in a paragraph. It can give '\ 'values as to where the word is located with the '\ 'different examples as stated' # find all occurances of the word 'as' in the above text find_the_word = re.finditer('as', text) for match in find_the_word: print('start {}, end {}, search string \'{}\''. format(match.start(), match.end(), match.group())) 

Cualquiera que sea la solución provista por otros, está completamente basada en el método de búsqueda () o en cualquier método disponible.

¿Cuál es el algoritmo básico básico para encontrar todas las apariciones de una subcadena en una cadena?

 def find_all(string,substring): """ Function: Returning all the index of substring in a string Arguments: String and the search string Return:Returning a list """ length = len(substring) c=0 indexes = [] while c < len(string): if string[c:c+length] == substring: indexes.append(c) c=c+1 return indexes 

También puede heredar la clase str a la nueva clase y puede usar esta función a continuación.

 class newstr(str): def find_all(string,substring): """ Function: Returning all the index of substring in a string Arguments: String and the search string Return:Returning a list """ length = len(substring) c=0 indexes = [] while c < len(string): if string[c:c+length] == substring: indexes.append(c) c=c+1 return indexes 

Llamando al método

newstr.find_all ('¿Le parece útil esta respuesta? ¡Entonces, promueva esto!', 'este')

Puedes probar :

 >>> string = "test test test test" >>> for index,value in enumerate(string): if string[index:index+(len("test"))] == "test": print index 0 5 10 15 

Puede utilizar fácilmente:

 string.count('test')! 

https://www.programiz.com/python-programming/methods/string/count

¡Aclamaciones!

Cuando busque una gran cantidad de palabras clave en un documento, use flashtext

 from flashtext import KeywordProcessor words = ['test', 'exam', 'quiz'] txt = 'this is a test' kwp = KeywordProcessor() kwp.add_keywords_from_list(words) result = kwp.extract_keywords(txt, span_info=True) 

Flashtext se ejecuta más rápido que las expresiones regulares en una gran lista de palabras de búsqueda.

La forma pythonica sería:

 mystring = 'Hello World, this should work!' find_all = lambda c,s: [x for x in range(c.find(s), len(c)) if c[x] == s] # s represents the search string # c represents the character string find_all(mystring,'o') # will return all positions of 'o' [4, 7, 20, 26] >>> 

por favor mira el siguiente código

 #!/usr/bin/env python # coding:utf-8 '''黄哥Python''' def get_substring_indices(text, s): result = [i for i in range(len(text)) if text.startswith(s, i)] return result if __name__ == '__main__': text = "How much wood would a wood chuck chuck if a wood chuck could chuck wood?" s = 'wood' print get_substring_indices(text, s)