2009-06-06 2 views
13

У меня есть некоторая строка шаблонабыстрый способ заменить строку в шаблоне

это мой {0} шаблон {1} Строка

, который я планирую поставить пользовательские значения при помощи String.Format().

Строка на самом деле больше так для удобства чтения я использую:

это мой {goodName1} шаблон {goodName2} Строка

И тогда String.Replace каждый параметр со значением.

Как я могу получить максимальную производительность и удобочитаемость?

Возможно, у меня не должно быть этого шаблона в файле (как сейчас), но динамически строить его путем объединения в построитель строк и добавления параметров при необходимости? Хотя это менее читаемо.

Какие у меня другие варианты?

+1

Жалко этот вопрос превратился в дискуссия о скорости. У еще более сложного решения «String.Replace». Если заменяющий текст также содержит подстроки формы '{goodNameN}', то они будут расширены или нет? Оказывается, это зависит от порядка, в котором выполняются замены. Это та тонкая нечеткость, которая может лежать безвредно годами, а затем укусить загадочными способами задолго до того, как код забыт. –

ответ

14
+18

Не соглашайтесь - это может иметь значение. Просто * убедитесь, что это важно, прежде чем оптимизировать, а не предполагать это. – Brian

+4

Иногда это действительно имеет значение ... так как в этом случае, когда Replace был настроен с 20 секунд до 0,1 ... http://www.codeproject.com/Articles/298519/Fast-Token-Replacement-in-Csharp –

7

Как и все, от этого зависит. Если код будет называться миллионы раз каждый день, подумайте о производительности. Если это несколько раз в день, тогда идите на удобочитаемость.

Я провела сравнительный анализ между использованием обычных (неизменяемых) строк и StringBuilder. До тех пор, пока вы не начнете делать огромные суммы за небольшие промежутки времени, вам не нужно слишком беспокоиться об этом.

+1

Я согласен с Иэном. Для получения дополнительной информации ознакомьтесь с этой статьей о проекте кода: http://www.codeproject.com/KB/string/string.aspx – Kane

7

Моего спонтанное решение будет выглядеть следующим образом:

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." 

Я использовал этот вид замены шаблонов в нескольких реальных проектах и ​​никогда не нашел, что это проблема производительности. Поскольку он прост в использовании и понимании, я не видел причин его сильно менять.

37

Вы можете поместить параметры в словарь и использовать метод Regex.Replace для замены всех параметров в одной замене. Таким образом, метод хорошо масштабируется, если строка шаблона становится длинной или число параметров растет.

Пример:

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

Это решение является наиболее эффективным, вы должны использовать какой-либо метод расширения, чтобы позаботиться о том, -высокие ключи при поиске словаря. –

+0

И \ {([^}] +) \} быстрее, чем использование неживого оператора. –

+0

@ Guffa - Хорошее примечание, чтобы указать, что 'm.Value' должно быть' m.Groups [1] .Value'. 'm.Value' возвращает то же, что и' m.Groups [0] .Value', который соответствует всей части. – Zack

1

быстрый способ сделать это с StringBuilder, используя индивидуальные вызовы StringBuilder.Append(), как это:

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

Я thoroughly benchmarked the framework code, и это будет будьте быстрым. Если вы хотите улучшить читаемость, вы можете сохранить отдельную строку, чтобы показать пользователя, и просто используйте это в фоновом режиме.

+2

Вам не нужно это делать. Компилятор C# скомпилирует это точно так же, как если бы вы просто выполнили 'string result =", это мой шаблон + UserVar1 + "+ UserVar2 +" string "' –

0

Если вам нужен хороший, быстрый, но простой механизм шаблонов, вы должны проверить StringTemplate. Для простых шаблонов, которые не требуют никакой логики или управления потоком в самом шаблоне, StringTemplate GREAT.

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

3

БЕРЕГИТЕСЬ погрязнуть с этим типом мышления. Если этот код не работает сотни раз в минуту, а файл шаблона имеет размер несколько К, более важно сделать это. Не тратьте минутку на размышления о таких проблемах. В общем, если вы много работаете со строковыми манипуляциями, используйте конструктор строк. У него даже есть метод замены. Но, зачем беспокоиться. Когда вы закончите, и если вы обнаружите, что у вас проблема с производительностью, используйте PerfMon и исправьте узкие места REAL в то время.

1

То же самое выше, что Фредрик размещен выше, но с 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

модернизировали выше ответ на следующий: метод

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

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

    data.Parse(replacements); 

Extension:

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; 
    } 
} 

Надежда это помогает .. :)