Encontrar una cadena varias veces en otra cadena – Python

Estoy intentando ver si existe una cadena en otra cadena sin utilizar las funciones predefinidas de Python, como buscar e indexar …

En este momento, lo que mi función toma 2 cadenas como parámetros, una es la cadena que vamos a buscar, mientras que la otra cadena es lo que estamos buscando en la primera cadena.

Si la segunda cadena existe en la primera, quiero que mi función devuelva todas las posiciones en la primera cadena.

En este momento, mi función es capaz de encontrar la primera aparición y devolver un índice, sin embargo, quiero encontrar varias apariciones en lugar de la primera.

A continuación se muestra mi código:

def multi_find (s, r): s_len = len(s) r_len = len(r) if s_len < r_len: n = -1 else: m = s_len - r_len n = -1 # assume r is not yet found in s i = 0 while n == -1 and i < m: # search for r in s until not enough characters are left if s[i:i + r_len] == r: n = i else: i = i + 1 print (n) multi_find("abcdefabc. asdli! ndsf acba saa abe?", "abc") 

En este momento, esto generará solo “0” porque ahí es donde abc se produce primero. ¿Cómo puedo hacer que devuelva “0” y “6” (el comienzo de la segunda aparición)? Básicamente, siga revisando después de encontrar uno.

Estaba pensando en algo así como crear una lista de todos los lugares en los que ocurre y luego agregar i a esa lista, pero cuando lo intenté, nada me funcionaba.

Tu puedes hacer:

 >>> haystack = "abcdefabc. asdli! ndsf acba saa abe?" >>> needle = "abc" >>> for i, _ in enumerate(haystack): ... if haystack[i:i + len(needle)] == needle: ... print (i) ... 0 6 

Otra alternativa utilizando regex :

 >>> import re >>> haystack = "abcdefabc. asdli! ndsf acba saa abe?" >>> needle = "abc" >>> [m.start() for m in re.finditer(r'{}'.format(re.escape(needle)), haystack)] [0, 6] 

La solución anterior no funcionará para la superposición de cadenas secundarias, ya que hay 3 'aa' en 'aaaa' . Entonces, si también quieres encontrar coincidencias superpuestas, entonces:

 >>> haystack = "bobob" >>> needle = "bob" >>> [m.start() for m in re.finditer(r'(?={})'.format(re.escape(needle)), haystack)] [0, 2] 
 def multi_find(s, r): s_len = len(s) r_len = len(r) _complete = [] if s_len < r_len: n = -1 else: for i in xrange(s_len): # search for r in s until not enough characters are left if s[i:i + r_len] == r: _complete.append(i) else: i = i + 1 print(_complete) multi_find("abcdefabc. asdli! ndsf abc saa abe?", "abc") 
 def multi_find (s, r): s_len = len(s) r_len = len(r) n = [] # assume r is not yet found in s if s_len >= r_len: m = s_len - r_len i = 0 while i < m: # search for r in s until not enough characters are left if s[i:i + r_len] == r: n.append(i) i = i + 1 print (n) multi_find("abcdefabc. asdli! ndsf acba saa abe?", "abc") 

Casi simplemente reemplace n con una lista para que pueda seguir agregándole valores a medida que los encuentre. También debe boost i, incluso cuando se encuentra una coincidencia, se habría atascado en un bucle para siempre, excepto que tenía la restricción while n == -1 que la detuvo tan pronto como se encontró una coincidencia.

probablemente la mejor manera de hacerlo es seguir llamando a la función de búsqueda (esto también es más rápido)

 def multifind(string, value, start = 0, stop = None): values = [] while True: found = string.find(value, start, stop) if found == -1: break values.append(found) start = found + 1 return values print multifind('hello abc abc', 'abc') 

Salida:

 [6, 10] 

@Jacob, espero que encuentres este muy corto pero que aún sea fácil de entender.

 def multi_find(s, r): return [pos for pos in range(len(s)) if s.startswith(r,pos)] 

Nota: creo que esta respuesta aquí sigue siendo una buena “respuesta de enseñanza”, he presentado una mejor solución en otras partes de este hilo, sin recursión.

 def multi_find(s, r, start=0): if start >= len(s): return [] if s.startswith(r, start): return [start] + multi_find(s, r, start+1) else: return multi_find(s, r, start+1) 

Esto le permite pasar una posición de start opcional para comenzar la búsqueda en s .

Esta solución es recursiva, que puede ser o no la implementación más rápida, pero es correcta y creo que hace que el código sea fácil de identificar cada una de las tres posibilidades en cada posición de s :

  1. fin de s
  2. encontrado otra r
  3. no encontré otra r