2008-12-30 19 views
7

Digamos que he escrito una aplicación de administración de correo electrónico personalizada para la empresa para la que trabajo. Lee los correos electrónicos de la cuenta de soporte de la empresa y almacena versiones limpias y en texto sin formato de ellos en una base de datos, y hace otras cosas interesantes como asociarlas con cuentas de clientes y pedidos en el proceso. Cuando un empleado responde a un mensaje, mi programa genera un correo electrónico que se envía al cliente con una versión formateada del hilo de discusión. Si el cliente responde, la aplicación busca un número único en la línea de asunto para leer el mensaje entrante, eliminar la discusión anterior y agregarlo como un nuevo elemento en el hilo. Por ejemplo:Algoritmo para volver a envolver el texto envuelto?

 
This is a message from Contoso customer service. 

Recently, you requested customer support. Below is a summary of your 
request and our reply. 

-------------------------------------------------------------------- 
Contoso (Fred) on Tuesday, December 30, 2008 at 9:04 a.m. 
-------------------------------------------------------------------- 
John: 

I've modified your address. You can confirm my work by logging into 
"Your Account" on our Web site. Your order should ship out today. 

Thanks for shopping at Contoso. 

-------------------------------------------------------------------- 
You on Tuesday, December 30, 2008 at 8:03 a.m. 
-------------------------------------------------------------------- 
Oops, I entered my address incorrectly. Can you change it to 

Fred Smith 
123 Main St 
Anytown, VA 12345 

Thanks! 

-- 
Fred Smith 
Contoso Product Lover 

En general, todo esto funciona muy bien, pero hay un área que he tipo de posponer la limpieza desde hace un tiempo, y se ocupa de ajuste de texto. Para generar el bonito formato de correo electrónico como el anterior, necesito volver a ajustar el texto que el cliente envió originalmente.

He escrito un algoritmo que hace esto (aunque mirando el código, no estoy del todo seguro de cómo funciona, podría usar alguna refactorización). Pero no puede distinguir entre una nueva línea de envolvente dura, una nueva línea de "fin de párrafo" y una nueva línea "semántica". Por ejemplo, una nueva línea de envoltura dura es una que el cliente de correo electrónico insertó dentro de un párrafo para envolver una larga línea de texto, digamos, en 79 columnas. Una nueva línea de fin de párrafo es aquella que el usuario agregó después de la última oración de un párrafo. Y una nueva línea semántica sería algo así como la etiqueta br, como la dirección que Fred escribió arriba.

Mi algoritmo lugar sólo ve dos saltos de línea en una fila como indica un nuevo párrafo, por lo que tendría correo electrónico del cliente puede formatear algo como lo siguiente:

 
Oops, I entered my address incorrectly. Can you change it to 

Fred Smith 123 Main St Anytown, VA 12345 

Thanks! 

-- Fred Smith Contoso Product Lover 

cada vez que intento escribir una versión Eso volvería a envolver este texto como estaba previsto, básicamente toqué una pared en la que necesito saber la semántica del texto, la diferencia entre una línea nueva "hard-wrap" y un "Realmente lo quise decir como un tipo br" nueva línea, como en la dirección del cliente. (Utilizo dos nuevas líneas seguidas para determinar cuándo comenzar un nuevo párrafo, que coincide con la forma en que la mayoría de las personas realmente escriben correos electrónicos).

Cualquiera tiene un algoritmo que puede volver a ajustar el texto como ¿destinado a? ¿O esta implementación es "lo suficientemente buena" al sopesar la complejidad de una solución dada?

Gracias.

Respuesta

3

Puede intentar comprobar si se ha insertado una nueva línea para mantener la longitud de la línea por debajo de un máximo (también conocido como envoltura rígida): simplemente verifique la línea más larga del texto. Luego, para cualquier línea dada, le agrega la primera palabra de la siguiente línea. Si la línea resultante excede la longitud máxima, el salto de línea probablemente fue una envoltura difícil.

Aún más simple, podría considerar todas las rupturas en (maxlength - 15) <= length <= maxlength como hardwraps (con 15 simplemente como una conjetura). Esto sin duda filtrará las interrupciones intencionales, como las direcciones y otras cosas, y cualquier interrupción omitida en este rango no influiría demasiado en el resultado.

+0

Gracias por esta sencilla idea. Vea mi respuesta a continuación para una implementación de muestra rápida y sucia. –

2

Tengo dos sugerencias, de la siguiente manera.

  • Prestar atención a puntuacion: esto ayudará a distinguir entre un "duro-wrap" salto de línea y un "final del párrafo" nueva línea (ya que, si la línea termina con un punto, entonces es más probable que el usuario pretendía que fuera un final de párrafo.

  • Preste atención a si una línea es mucho más corta que la longitud máxima de línea: en el ejemplo anterior, puede tener texto "79-envuelto", además tiene líneas de dirección de solo 30 caracteres largo; porque 30 es mucho menos que 79, usted sabe que el usuario ha roto las líneas de dirección y no el algoritmo de ajuste de texto del usuario.

También, preste atención a los guiones: líneas que están sangrados con espacios en blanco de la izquierda se puede suponer que los nuevos párrafos, rotas desde las líneas anteriores, ya que están en este foro.

2

Siguiendo el consejo anterior de Ole, volví a trabajar en mi implementación para ver un umbral. Parece manejar la mayoría de los escenarios que arrojo lo suficientemente bien sin tener que volverme loco y escribir código que realmente entienda el idioma inglés.

Básicamente, primero escaneo a través de la cadena de entrada y registro la longitud de línea más larga en la variable inputMaxLineLength. Luego, mientras estoy reencaminando, si encuentro una nueva línea que tiene un índice entre inputMaxLineLength y 85% de inputMaxLineLength, entonces reemplazo esa nueva línea con un espacio porque creo que es una nueva línea dura, a menos que sea seguida inmediatamente por otra nueva línea, porque entonces supongo que es solo un párrafo de una línea lo que sucede dentro de ese rango. Esto puede suceder si alguien escribe una lista corta con viñetas, por ejemplo.

Sin duda no es perfecto, pero "lo suficientemente bueno" para mi escenario, teniendo en cuenta que el texto suele ser medio destrozado por un cliente de correo electrónico anterior, para empezar.

Aquí hay un código, mi aplicación de unas pocas horas de antigüedad que probablemente aún se desarrolle en algunos casos extremos (usando C#). Es mucho menos complicado que mi solución anterior, lo cual es bueno.

Source Code

Y aquí es algunas pruebas unitarias que ejercen ese código (utilizando MSTest):

Test Code

Si alguien tiene una mejor aplicación (y existe una mejor aplicación sin duda), I' Estaré feliz de leer tus pensamientos! Gracias.

Cuestiones relacionadas