¿Concatenar dos cadenas con una subcadena común?

Di que tengo cuerdas,

string1 = 'Hello how are you' string2 = 'are you doing now?' 

El resultado debe ser algo como

 Hello how are you doing now? 

Estaba pensando en diferentes maneras usando re y búsqueda de cadenas. ( El problema más largo de subcadena común )

Pero, ¿hay alguna forma simple (o biblioteca) que haga esto en python?

Para aclarar las cosas, agregaré un conjunto más de cadenas de prueba.

 string1 = 'This is a nice ACADEMY' string2 = 'DEMY you know!' 

¡El resultado sería!

 'This is a nice ACADEMY you know!' 

Esto debería hacer:

 string1 = 'Hello how are you' string2 = 'are you doing now?' i = 0 while not string2.startswith(string1[i:]): i += 1 sFinal = string1[:i] + string2 

SALIDA:

 >>> sFinal 'Hello how are you doing now?' 

O bien, conviértalo en una función para que pueda usarla de nuevo sin tener que volver a escribir:

 def merge(s1, s2): i = 0 while not s2.startswith(s1[i:]): i += 1 return s1[:i] + s2 

SALIDA:

 >>> merge('Hello how are you', 'are you doing now?') 'Hello how are you doing now?' >>> merge("This is a nice ACADEMY", "DEMY you know!") 'This is a nice ACADEMY you know!' 

Esto debería hacer lo que quieras:

 def overlap_concat(s1, s2): l = min(len(s1), len(s2)) for i in range(l, 0, -1): if s1.endswith(s2[:i]): return s1 + s2[i:] return s1 + s2 

Ejemplos:

 >>> overlap_concat("Hello how are you", "are you doing now?") 'Hello how are you doing now?' >>> >>> overlap_concat("This is a nice ACADEMY", "DEMY you know!") 'This is a nice ACADEMY you know!' >>> 

Usando str.endswith y enumerate :

 def overlap(string1, string2): for i, s in enumerate(string2, 1): if string1.endswith(string2[:i]): break return string1 + string2[i:] 
 >>> overlap("Hello how are you", "are you doing now?") 'Hello how are you doing now?' >>> overlap("This is a nice ACADEMY", "DEMY you know!") 'This is a nice ACADEMY you know!' 

Si tuviera que dar cuenta de los caracteres especiales finales, desearía emplear alguna sustitución basada en re .

 import re string1 = re.sub('[^\w\s]', '', string1) 

Aunque tenga en cuenta que esto eliminaría todos los caracteres especiales en la primera cadena.


Una modificación de la función anterior que encontrará la subcadena más larga coincidente (en lugar de la más corta) implica atravesar string2 en sentido inverso.

 def overlap(string1, string2): for i in range(len(s)): if string1.endswith(string2[:len(string2) - i]): break return string1 + string2[len(string2) - i:] 
 >>> overlap('Where did', 'did you go?') 'Where did you go?' 

Otras respuestas fueron geniales, pero fallaron para esta entrada.

 string1 = 'THE ACADEMY has' string2= '.CADEMY has taken' 

salida:

 >>> merge(string1,string2) 'THE ACADEMY has.CADEMY has taken' >>> overlap(string1,string2) 'THE ACADEMY has' 

Sin embargo, ¡existe esta biblioteca estándar difflib que resultó ser efectiva en mi caso!

 match = SequenceMatcher(None, string1,\ string2).find_longest_match\ (0, len(string1), 0, len(string2)) print(match) # -> Match(a=0, b=15, size=9) print(string1[: match.a + match.size]+string2[match.b + match.size:]) 

salida:

 Match(a=5, b=1, size=10) THE ACADEMY has taken 

las palabras que desea reemplazar aparecen en la segunda cadena para que pueda probar algo como:

 new_string=[string2.split()] new=[] new1=[j for item in new_string for j in item if j not in string1] new1.insert(0,string1) print(" ".join(new1)) 

con el primer caso de prueba:

 string1 = 'Hello how are you' string2 = 'are you doing now?' 

salida:

 Hello how are you doing now? 

segundo caso de prueba:

 string1 = 'This is a nice ACADEMY' string2 = 'DEMY you know!' 

salida:

 This is a nice ACADEMY you know! 

Explicación:

Primero, estamos dividiendo la segunda cadena para que podamos encontrar qué palabras debemos eliminar o reemplazar:

 new_string=[string2.split()] 

segundo paso revisaremos cada palabra de esta cadena divisoria con cadena1, si hay alguna palabra en esa cadena que elija solo la primera palabra de cadena, deje esa palabra en la segunda cadena:

 new1=[j for item in new_string for j in item if j not in string1] 

Esta lista de comprensión es la misma que:

 new1=[] for item in new_string: for j in item: if j not in string1: new1.append(j) 

El último paso combina tanto la cadena como unirse a la lista:

 new1.insert(0,string1) print(" ".join(new1))