Лучший способ заменить токены в большом текстовом шаблоне - PullRequest
13 голосов
/ 21 августа 2008

У меня большой текстовый шаблон, которому нужно заменить токенизированные разделы другим текстом. Токены выглядят примерно так: ## USERNAME ##. Мой первый инстинкт - просто использовать String.Replace (), но есть ли лучший, более эффективный способ или Replace () уже оптимизирован для этого?

Ответы [ 10 ]

12 голосов
/ 21 августа 2008

System.Text.RegularExpressions.Regex.Replace () - это то, что вы ищете - ЕСЛИ ваши токены достаточно странны, так что вам нужно регулярное выражение для их поиска.

Какой-то добрый соул провел некоторое тестирование производительности , и между Regex.Replace (), String.Replace () и StringBuilder.Replace (), String.Replace () фактически вышел на первое место.

7 голосов
/ 21 августа 2008

Единственная ситуация, в которой мне приходилось это делать, это отправка шаблонного электронного письма. В .NET это обеспечивается из коробки MailDefinition класс . Вот как вы создаете шаблонное сообщение:

MailDefinition md = new MailDefinition();
md.BodyFileName = pathToTemplate;
md.From = "test@somedomain.com";

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

MailMessage msg = md.CreateMailMessage("test@someotherdomain.com", replacements, this);

После этого msg.Body будет создан путем замены значений в шаблоне. Я думаю, вы можете взглянуть на MailDefinition.CreateMailMessage () с Reflector :). Извините за то, что я немного не по теме, но если это ваш сценарий, я думаю, что это самый простой способ.

3 голосов
/ 22 августа 2008

Ну, в зависимости от того, сколько переменных у вас есть в вашем шаблоне, сколько шаблонов у вас есть и т. Д., Это может подойти для полного процессора шаблонов. Единственный, который я когда-либо использовал для .NET, это NVelocity , но я уверен, что там должно быть множество других, большинство из которых связано с какой-то веб-структурой или другим.

2 голосов
/ 12 июля 2012

FastReplacer реализует замену токена за O (n * log (n) + m) и использует в 3 раза больше памяти исходной строки.

FastReplacer хорош для выполнения многих операций замены на большой строке, когда важна производительность.

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

Мы разработали FastReplacer, чтобы помочь нам в проекте, где нам пришлось генерировать большой текст с большим количеством операций добавления и замены. Первая версия приложения заняла 20 секунд, чтобы сгенерировать текст с помощью StringBuilder. Вторая улучшенная версия, которая использовала класс String, заняла 10 секунд. Затем мы реализовали FastReplacer, и продолжительность сократилась до 0,1 секунды.

2 голосов
/ 21 августа 2008

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

Лучшим подходом будет определение токена, например, вашего "##", который вы можете сканировать в тексте. Затем выберите, что заменить из хеш-таблицы текстом, который следует за токеном в качестве ключа.

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

2 голосов
/ 21 августа 2008

Пришлось сделать нечто подобное в последнее время. То, что я сделал, было:

  • создать метод, который принимает словарь (ключ = имя токена, значение = текст, который нужно вставить)
  • Получить все совпадения с вашим форматом токена (##. +? ## в вашем случае, я думаю, не очень хорошо для регулярных выражений: P) с использованием Regex.Matches (input, регулярное выражение)
  • foreach поверх результатов, используя словарь, чтобы найти значение вставки для вашего токена.
  • результат возврата.

Готово; -)

Если вы хотите проверить свои регулярные выражения, я могу предложить регулятор.

2 голосов
/ 21 августа 2008

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

2 голосов
/ 21 августа 2008

строка. Замена в порядке. Я бы предпочел использовать Regex, но я *** для регулярных выражений.

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

Но, для реализации наивный, string.Replace должно быть хорошо.

1 голос
/ 03 сентября 2011

Если ваш шаблон большой и у вас много токенов, вы, вероятно, не хотите его обойти и заменить токен в шаблоне один за другим, так как это приведет к операции O (N * M), где N - это размер шаблона, а M - количество токенов для замены.

Следующий метод принимает шаблон и словарь пар ключей-значений, которые вы хотите заменить. Если инициализировать StringBuilder немного большим, чем размер шаблона, это должно привести к операции O (N) (т. Е. Ему не нужно увеличивать сам журнал N раз).

Наконец, вы можете переместить здание токенов в синглтон, так как его нужно сгенерировать только один раз.

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();
}
0 голосов
/ 21 августа 2008

Это идеальное использование регулярных выражений. Посетите этот полезный веб-сайт , класс регулярных выражений .Net и эту очень полезную книгу Освоение регулярных выражений .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...