Лучший способ заменить токены в большом текстовом шаблоне

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

21.08.2008 15:36:24
10 ОТВЕТОВ
РЕШЕНИЕ

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

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

12
21.08.2008 16:23:53
Я считаю, что они сделали свой тест в PowerShell, который не относится к C #. C3 имеет другое управление памятью от PowerShell и не преобразует StringBuilder в String для замены символов в нем. С другой стороны, RegEx и StringBuilder лучше работают с большими
AaA 24.04.2013 07:38:49
RegEx - ужасная опция для замены большого количества текста. Несмотря на свою мощь, многие сторонники RegEx видят весь мир как гвоздь, а RegEx - как молоток. Для случаев использования, включающих большое количество текста, посмотрите на FastReplacer stackoverflow.com/a/11442008/141172
Eric J. 5.11.2014 17:57:05

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

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

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

2
21.08.2008 15:40:05

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

2
21.08.2008 15:40:47

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

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

Выполнено ;-)

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

2
22.08.2008 00:30:29

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

0
21.08.2008 15:57:37

Единственная ситуация, в которой мне приходилось это делать, это отправка шаблонного электронного письма. В .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 :). Извините, что немного не в тему, но если это ваш сценарий, я думаю, что это самый простой способ.

7
21.08.2008 15:58:46

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

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

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

2
21.08.2008 16:41:03

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

3
22.08.2008 01:12:30

Если ваш шаблон большой и у вас много токенов, вы, вероятно, не хотите его обойти и заменить токен в шаблоне один за другим, так как это приведет к операции O (N * M), где N - размер template и 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();
}
1
3.09.2011 05:15:16

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

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

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

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

2
11.07.2012 21:48:16
Это то, что я искал. Пожалуйста, проверьте таблицу скорости и попробуйте.
Marek Bar 5.11.2014 07:52:51