2012-05-27 8 views
6

Tengo la siguiente función que obtiene una fuente y una cadena modificada, y repite las palabras modificadas en ella.Encontrar diferencias entre cadenas

def appendBoldChanges(s1, s2): 
    "Adds <b></b> tags to words that are changed" 
    l1 = s1.split(' ') 
    l2 = s2.split(' ') 
    for i, val in enumerate(l1): 
     if l1[i].lower() != l2[i].lower(): 
      s2 = s2.replace(l2[i], "<b>%s</b>" % l2[i]) 

    return s2 
print appendBoldChanges("britney spirs", "britney spears") # returns britney <b>spears</b> 

Funciona bien en las cadenas con la misma cuenta de la palabra, pero falla con diferentes cuentas de la palabra, como sora iro days y sorairo days.

¿Cómo puedo tener en cuenta el espaciado?

+0

@mata En realidad puede hacer que una respuesta. :) – SuperSaiyan

+0

@Thrustmaster - como lo desee: b – mata

Respuesta

21

usted podría utilizar difflib, y hacerlo de esta manera:

from difflib import Differ 

def appendBoldChanges(s1, s2): 
    "Adds <b></b> tags to words that are changed" 
    l1 = s1.split(' ') 
    l2 = s2.split(' ') 
    dif = list(Differ().compare(l1, l2)) 
    return " ".join(['<b>'+i[2:]+'</b>' if i[:1] == '+' else i[2:] for i in dif 
                  if not i[:1] in '-?']) 

print appendBoldChanges("britney spirs", "britney sprears") 
print appendBoldChanges("sora iro days", "sorairo days") 
#Output: 
britney <b>sprears</b> 
<b>sorairo</b> days 
+1

+1 para un soberbio trazador de líneas. Es posible que desee limpiar la cadena devuelta. Ingrese 'appendBoldChanges (" sorairo days "," sora iro days ")' resultados en 'sorairo días' cuando OP probablemente necesite' sora iro days'. Elegancia verdaderamente pitonica. – gauden

+0

@gauden - aplausos;) Pensé que probablemente no importaría ya que muestran lo mismo. Si es un problema, entonces sí, '.replace ('', '')' al final, sería la solución .. – fraxel

+0

Estoy seguro de que tienes razón :) – gauden

1

Una pequeña actualización tp @fraxel respuesta que devuelve 2 salidas - el original y la nueva versión con cambios marcados. I también cambiar la de una sola línea a una versión más fácil en mi opinión

def show_diff(text, n_text): 
    seqm = difflib.SequenceMatcher(None, text, n_text) 
    output_orig = [] 
    output_new = [] 
    for opcode, a0, a1, b0, b1 in seqm.get_opcodes(): 
     orig_seq = seqm.a[a0:a1] 
     new_seq = seqm.b[b0:b1] 
     if opcode == 'equal': 
      output_orig.append(orig_seq) 
      output_new.append(orig_seq) 
     elif opcode == 'insert': 
      output_new.append("<font color=green>{}</font>".format(new_seq)) 
     elif opcode == 'delete': 
      output_orig.append("<font color=red>{}</font>".format(orig_seq)) 
     elif opcode == 'replace': 
      output_new.append("<font color=blue>{}</font>".format(new_seq)) 
      output_orig.append("<font color=blue>{}</font>".format(orig_seq)) 
     else: 
      print('Error') 
    return ''.join(output_orig), ''.join(output_new) 
Cuestiones relacionadas