Pregunta

Digamos que he escrito una aplicación de gestión de correo electrónico personalizada para la empresa para la que trabajo.Lee correos electrónicos de la cuenta de soporte de la compañía y almacena versiones limpias de texto sin formato en una base de datos, haciendo otras cosas interesantes como asociarlo 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 agregarla como un nuevo elemento en el hilo.Por ejemplo:

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 pospuesto la limpieza por un tiempo y tiene que ver con el ajuste de texto.Para generar un bonito formato de correo electrónico como el de arriba, necesito volver a ajustar el texto que el cliente envió originalmente.

He escrito un algoritmo que hace esto (aunque al mirar el código, ya no estoy del todo seguro de cómo funciona; le vendría bien algo de refactorización). Pero no puede distinguir entre una nueva línea estricta, una nueva línea de "fin de párrafo" y una nueva línea "semántica". Por ejemplo, una nueva línea de ajuste rígido es aquella que el cliente de correo electrónico inserta dentro de un párrafo para ajustar una línea larga de texto, digamos, en 79 columnas.Una nueva línea de final 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 br etiqueta, como la dirección que Fred escribió arriba.

En cambio, mi algoritmo solo ve dos nuevas líneas seguidas como indicación de un nuevo párrafo, por lo que haría que el correo electrónico del cliente tuviera un formato similar al 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 que reenvuelva este texto como estaba previsto, básicamente me topo con un muro porque necesito conocer la semántica del texto, la diferencia entre una nueva línea "duro" y un "realmente quise decir". es como un br"-escriba una 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, lo que coincide con la forma en que la mayoría de las personas parecen escribir los correos electrónicos).

¿Alguien tiene un algoritmo que pueda volver a ajustar el texto según lo previsto?¿O es esta implementación "suficientemente buena" cuando se sopesa la complejidad de cualquier solución determinada?

Gracias.

¿Fue útil?

Solución

Puede intentar verificar 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): solo verifique la línea más larga en el texto. Luego, para cualquier línea dada, 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 dura.

Aún más simple, podría considerar todos los descansos en (maxlength - 15) <= length <= maxlength como envolturas (con 15 como una suposición educada). Esto ciertamente filtraría los descansos intencionales como en las direcciones y otras cosas, y cualquier descanso perdido en este rango no afectaría demasiado el resultado.

Otros consejos

Tengo dos sugerencias, como sigue.

  • Presta atención a la puntuación: esto te ayudará a distinguir entre un " hard-wrap " nueva línea y un " final del párrafo " nueva línea (porque, si la línea termina con un punto, entonces es más probable que el usuario pretenda que sea un final de párrafo.

  • Preste atención a si una línea es mucho más corta que la longitud máxima de la línea: en el ejemplo anterior, es posible que tenga texto que está siendo " hard-wrap " con 79 caracteres, además tiene líneas de dirección que solo tienen 30 caracteres; porque 30 es mucho menos que 79, usted sabe que las líneas de dirección fueron interrumpidas por el usuario y no por el algoritmo de ajuste de texto del usuario.

Además, preste atención a las sangrías: se puede suponer que las líneas que están sangradas con espacios en blanco desde la izquierda son párrafos nuevos, separados de las líneas anteriores, como están en este foro.

Siguiendo el consejo anterior de Ole, reelaboré mi implementación para buscar un umbral.Parece manejar la mayoría de los escenarios que le planteo bastante bien sin tener que volverme loco y escribir código que realmente entienda el idioma inglés.

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

Ciertamente no es perfecto, pero es "suficientemente bueno" para mi escenario, considerando que, para empezar, el texto generalmente está medio destrozado por un cliente de correo electrónico anterior.

Aquí hay algo de código, mi implementación de hace unas horas que probablemente todavía se incluye en algunos casos extremos (usando C#).Es mucho menos complicado que mi solución anterior, lo cual es bueno.

Código fuente

Y aquí hay algunas pruebas unitarias que ejercitan ese código (usando MSTest):

Código de prueba

Si alguien tiene una implementación mejor (y sin duda existe una implementación mejor), ¡estaré encantado de leer su opinión!Gracias.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top