2008-08-21 9 views

Respuesta

12

System.Text.RegularExpressions.Regex.Replace() es lo que buscas - SI tus tokens son tan extraños que necesitas una expresión regular para encontrarlos.

Some kind soul did some performance testing, y entre Regex.Replace(), String.Replace(), y StringBuilder.Replace(), String.Replace() realmente salió en la parte superior.

+1

Creo que hicieron su prueba en PowerShell que no se aplica a C#. C3 tiene una gestión de memoria diferente de PowerShell y no convierte StringBuilder en String para reemplazar caracteres en él. Por otro lado, RegEx y StringBuilder funcionan mejor en tamaños de datos grandes que se agregan a ellos en fragmentos – AaA

+0

RegEx es una opción horrible para realizar sustituciones en una gran cantidad de texto. Tan poderoso como es, muchos proponentes de RegEx ven todo el mundo como un clavo y RegEx como su martillo. Para casos de uso que involucren grandes cantidades de texto, consulte FastReplacer http://stackoverflow.com/a/11442008/141172 –

2

string.Replace is fine. Preferiría usar un Regex, pero estoy loco por expresiones regulares.

Lo importante a tener en cuenta es cuán grandes son estas plantillas. Si es realmente grande, y la memoria es un problema, es posible que desee crear un tokenizador personalizado que actúe en una secuencia. De esta forma, solo mantendrá una pequeña parte del archivo en la memoria mientras lo manipula.

Pero, para la implementación ingenua, string.Replace debería estar bien.

2

Si está haciendo reemplazos múltiples en cadenas grandes, entonces podría ser mejor usar StringBuilder.Replace(), ya que aparecerán los problemas de rendimiento habituales con cadenas.

2

Tuve que hacer algo similar recientemente. Lo que hice fue:

  • crea un método que toma un diccionario (= nombre de símbolo de clave, valor = el texto debe insertar)
  • conseguir todas las coincidencias con el formato de fichas (## + #.? # en su caso, supongo que no es bueno en expresiones regulares: P) usando Regex.Matches (entrada, expresión regular)
  • busque los resultados, usando el diccionario para encontrar el valor de inserción para su token.
  • resultado de devolución.

Done ;-)

Si desea probar sus expresiones regulares que puedo sugerir the regulator.

7

La única situación en la que he tenido que hacer esto es enviar un correo electrónico con plantilla. En .NET esto se proporciona de fábrica por el MailDefinition class. Así que esta es la forma de crear un mensaje con plantilla:

MailDefinition md = new MailDefinition(); 
md.BodyFileName = pathToTemplate; 
md.From = "[email protected]"; 

ListDictionary replacements = new ListDictionary(); 
replacements.Add("<%To%>", someValue); 
// continue adding replacements 

MailMessage msg = md.CreateMailMessage("[email protected]", replacements, this); 

Después de esto, msg.Body se crearía mediante la sustitución de los valores en la plantilla. Supongo que puedes echar un vistazo a MailDefinition.CreateMailMessage() con Reflector :). Perdón por estar un poco fuera de tema, pero si este es su escenario, creo que es la manera más fácil.

2

Las expresiones regulares serían la solución más rápida para codificar, pero si tiene muchos tokens diferentes, se volverá más lento. Si el rendimiento no es un problema, utiliza esta opción.

Un mejor enfoque sería definir token, como su "##" que puede buscar en el texto.Luego, seleccione qué reemplazar de una tabla hash con el texto que sigue al token como la clave.

Si esto es parte de un script de compilación, entonces nAnt tiene una gran característica para hacer esto llamado Filter Chains. El código para eso es de código abierto para que pueda ver cómo se hace para una implementación rápida.

3

Bueno, dependiendo de cuántas variables tiene en su plantilla, cuántas plantillas tiene, etc. esto podría ser un trabajo para un procesador de plantillas completo. El único que he usado para .NET es NVelocity, pero estoy seguro de que debe haber muchos otros, la mayoría de ellos vinculados a algún framework web u otro.

1

Si su plantilla es grande y tiene muchos tokens, probablemente no desee caminar y reemplazar el token en la plantilla uno por uno, ya que eso daría como resultado una operación O (N * M) donde N es el tamaño de la plantilla y M es el número de tokens para reemplazar.

El siguiente método acepta una plantilla y un diccionario de los pares de valores de claves que desea reemplazar. Al inicializar StringBuilder a un tamaño ligeramente mayor que el tamaño de la plantilla, debería dar como resultado una operación O (N) (es decir, no debería tener que crecer por sí mismo el registro N veces).

Finalmente, puede mover la construcción de los tokens a Singleton ya que solo necesita generarse una vez.

static string SimpleTemplate(string template, Dictionary<string, string> replacements) 
{ 
    // parse the message into an array of tokens 
    Regex regex = new Regex("(##[^#]+##)"); 
    string[] tokens = regex.Split(template); 

    // the new message from the tokens 
    var sb = new StringBuilder((int)((double)template.Length * 1.1)); 
    foreach (string token in tokens) 
     sb.Append(replacements.ContainsKey(token) ? replacements[token] : token); 

    return sb.ToString(); 
} 
2

FastReplacer implementa la sustitución de tokens en O (log n * (n) + m) tiempo y utiliza 3x la memoria de la cadena original.

FastReplacer es bueno para ejecutar muchas operaciones de reemplazo en una cadena grande cuando el rendimiento es importante.

La idea principal es evitar modificar el texto existente o asignar memoria nueva cada vez que se reemplaza una cadena.

Diseñamos FastReplacer para ayudarnos en un proyecto en el que tuvimos que generar un texto grande con una gran cantidad de operaciones de agregar y reemplazar. La primera versión de la aplicación tardó 20 segundos en generar el texto usando StringBuilder. La segunda versión mejorada que utilizó la clase String tomó 10 segundos. Luego implementamos FastReplacer y la duración se redujo a 0.1 segundos.

+0

Esto es lo que estaba buscando. Por favor revisa la tabla de velocidad y pruébalo. –

Cuestiones relacionadas