Tengo una plantilla de texto grande que necesita secciones tokenizadas reemplazadas por otro texto. Los tokens se ven más o menos así: ## NOMBRE DE USUARIO ##. Mi primer instinto es simplemente utilizar String.Replace(), pero ¿hay una forma mejor y más eficiente o ya está Optimizado para esto?La mejor manera de reemplazar tokens en una plantilla de texto grande
Respuesta
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.
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.
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.
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.
Este es un uso ideal de expresiones regulares. Consulte this helpful website, .Net Regular Expressions class, y este muy útil libro Mastering Regular Expressions.
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.
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.
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.
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();
}
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.
Esto es lo que estaba buscando. Por favor revisa la tabla de velocidad y pruébalo. –
- 1. Una mejor manera de reemplazar muchas cadenas: ofuscación en C#
- 2. Gradle: Reemplazar tokens encontrando los tokens del archivo de propiedades
- 3. ¿Cuál es la MEJOR manera de reemplazar texto en un archivo usando C#/.NET?
- 4. PIL ¿Mejor manera de reemplazar el color?
- 5. ¿Cómo reemplazar pares de tokens en una cadena?
- 6. ¿Una mejor manera de reemplazar emoticones en PHP?
- 7. manera más rápida para reemplazar cadena en una plantilla
- 8. La mejor manera de almacenar el árbol de prefijo grande
- 9. ¿Cuál es la mejor manera de reemplazar remote.origin.url en Git?
- 10. models.py hacerse grande, ¿cuál es la mejor manera de romperlo?
- 11. mejor manera de analizar espacio separado del texto
- 12. Lectura de texto grande de manera eficiente en C++
- 13. ¿Cuál es la mejor manera de analizar una gramática simple?
- 14. ¿Cuál es la mejor manera de eliminar toda una tabla grande en t-sql?
- 15. ¿Cuál es la mejor manera de leer y analizar un archivo de texto grande a través de la red?
- 16. La mejor manera de crear un PDF con PHP
- 17. ¿Cuál es la mejor manera de rellenar una plantilla de Word 2007 en C#?
- 18. ¿Cuál es la mejor manera de almacenar datos de área para una aventura de texto?
- 19. Buscar y reemplazar en un archivo grande
- 20. ¿Coincidir una cadena en un archivo de texto grande?
- 21. Texto grande en Android
- 22. ¿Cuál es la mejor manera de duplicar datos en una plantilla django?
- 23. Delphi: la mejor manera de convertir rtf a texto
- 24. ¿La mejor manera de dibujar texto con OpenGL y Cocoa?
- 25. La mejor manera de codificar y decodificar texto PHP
- 26. ¿La mejor manera de definir una cadena vba grande, es decir, el equivalente heredoc?
- 27. ¿La mejor manera de analizar un archivo de coma flotante grande almacenado en ASCII?
- 28. ¿Cuál es la mejor manera de escribir un archivo grande en un disco en PHP?
- 29. La mejor manera de ordenar una matriz
- 30. La mejor manera de obtener valores distintos de la tabla grande
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
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 –