2009-06-06 27 views
13

que tienen alguna cadena de plantillamanera más rápida para reemplazar cadena en una plantilla

este es mi {0} plantilla {1} cadena

que pienso poner los valores de usuario en el uso de String.Format().

La cadena es en realidad más tiempo así para facilitar la lectura que utilizo:

este es mi {} goodName1 plantilla de cadena {} goodName2

Y luego String.Replace cada parámetro con su valor.

¿Cómo puedo obtener el mayor rendimiento y legibilidad?

Tal vez no debería tener esta plantilla en un archivo (como ahora) pero construirla dinámicamente mediante concatenación a un generador de cadenas y agregar los parámetros cuando sea necesario. Aunque es menos legible.

¿Cuáles son mis otras opciones?

+1

Es una lástima esta pregunta se convirtió en un debate sobre la velocidad. La solución replegada 'String.Replace' tiene un problema peor. Si el texto de reemplazo también contiene subcadenas de la forma '{goodNameN}', ¿se expandirán o no? Resulta que depende del orden en que se realizan los reemplazos. Este es el tipo de confusión sutil que puede ser inofensivo durante años y luego morder de formas misteriosas mucho después de que se olvide el código. –

Respuesta

14
+18

Tengo que estar en desacuerdo, puede ser importante. Solo * asegúrese * de que es importante antes de optimizar, en lugar de asumirlo. – Brian

+4

A veces realmente importa ... como en este caso donde Replace se sintonizó de 20 segundos a 0.1 ... http://www.codeproject.com/Articles/298519/ Fast-Token-Replacement-in-Csharp –

7

Como cualquier cosa, depende. Si el código se llamará millones de veces al día, entonces piense en el rendimiento. Si es unas pocas veces al día, luego busque legibilidad.

He hecho algunas evaluaciones comparativas entre el uso de cadenas normales (inmutables) y StringBuilder. Hasta que comiences a hacer una gran cantidad en poco tiempo, no tienes que preocuparte demasiado por eso.

+1

Estoy de acuerdo con Iain. Para obtener más información, consulte este artículo sobre Code Project: http://www.codeproject.com/KB/string/string.aspx – Kane

7

Mi solución espontánea se vería así:

string data = "This is a {template1} that is {template2}."; 

Dictionary<string, string> replacements = new Dictionary<string, string>(){ 
    {"{template1}", "car"}, 
    {"{template2}", "red"}, 
}; 

foreach (string key in replacements.Keys) 
{ 
    data = data.Replace(key, replacements[key]); 
} 
Console.WriteLine(data); // outputs "This is a car that is red." 

he utilizado este tipo de sustituciones de plantilla en varios proyectos del mundo real y nunca han encontrado que es un problema de rendimiento. Como es fácil de usar y comprender, no he visto ninguna razón para cambiarlo mucho.

37

Puede poner los parámetros en un diccionario y usar el método Regex.Replace para reemplazar todos los parámetros en un reemplazo. De esta forma, el método se adapta bien si la cadena de la plantilla se alarga o aumenta la cantidad de parámetros.

Ejemplo:

Dictionary<string, string> parameters = new Dictionary<string, string>(); 
parameters.Add("goodName1", "asdf"); 
parameters.Add("goodName2", "qwerty"); 
string text = "this is my {goodName1} template {goodName2} string"; 
text = Regex.Replace(text, @"\{(.+?)\}", m => parameters[m.Groups[1].Value]); 
+0

Esta solución es la más eficaz, debe utilizar un método de extensión de algún tipo para ocuparse de no -existentes teclas cuando busca el diccionario sin embargo. –

+0

Y \ {([^}] +) \} es más rápido que usar el operador no codicioso. –

+0

@Guffa - Una buena nota para señalar es 'm.Value' debe ser' m.Groups [1] .Value' también. 'm.Value' devuelve lo mismo que' m.Groups [0] .Value', que es la parte completa coincidente. – Zack

1

El manera más rápida de hacerlo es con un StringBuilder mediante llamadas individuales a StringBuilder.Append(), así:

string result = new StringBuilder("this is my ") 
       .Append(UserVar1) 
       .Append(" template ") 
       .Append(UserVar2) 
       .Append(" string") 
       .ToString(); 

he thoroughly benchmarked the framework code, y esto hará sea más rápido. Si desea mejorar la legibilidad, puede mantener una cadena separada para mostrar al usuario, y simplemente utilizar esto en segundo plano.

+2

No necesita hacer esto. El compilador de C# compilará esto exactamente igual que si acabaras de hacer 'string result =" esta es mi plantilla "+ UserVar1 +" "+ UserVar2 +" string "' –

0

Si necesita una buena y rápida, pero simple motor de plantillas, que debe salir StringTemplate. Para plantillas simples que no requieren lógica o control de flujo en la plantilla en sí, StringTemplate es EXCELENTE.

http://www.stringtemplate.org/download.html

3

Cuidado con los enredarse con este tipo de pensamiento. A menos que este código se ejecute cientos de veces por minuto y el archivo de la plantilla tenga varios K de tamaño, es más importante hacerlo. No pierdas un minuto pensando en problemas como este. En general, si está haciendo mucho con manipulaciones de cadenas, utilice un generador de cadenas. Incluso tiene un método Reemplazar. Pero, ¿para qué molestarse? Cuando haya terminado, y si encuentra que tiene un problema de rendimiento, use PerfMon y solucione los cuellos de botella REALES en ese momento.

1

Lo mismo que Fredrick publicó anteriormente, pero con linq.

public static string FindandReplace(this string inputText, Dictionary<string, string> placeHolderValues) 
    { 
     if (!string.IsNullOrEmpty(inputText)) 
     { 
      return placeHolderValues.Keys.Aggregate(inputText, (current, key) => current.Replace(key, placeHolderValues[key])); 
     } 
     else return inputText; 
    } 
0

acaba de modificar la respuesta anterior a lo siguiente: método

string data = "This is a {template1} that is {template2}."; 

    Dictionary<string, string> replacements = new Dictionary<string, string>(){ 
     {"{template1}", "car"}, 
     {"{template2}", "red"}, 
    }; 

    data.Parse(replacements); 

Extensión:

public static class Parser 
{ 
    public static string Parse(this string template, Dictionary<string, string> replacements) 
    { 
     if (replacements.Count > 0) 
     { 
      template = replacements.Keys 
         .Aggregate(template, (current, key) => current.Replace(key, replacements[key])); 
     } 
     return template; 
    } 
} 

Espero que esto ayude .. :)

Cuestiones relacionadas