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

У меня есть большой текстовый шаблон, в котором нужно заменить токенизированные разделы другим текстом. Жетоны выглядят примерно так: ## ИМЯ ПОЛЬЗОВАТЕЛЯ ##. Мой первый инстинкт - просто использовать String.Replace (), но есть ли лучший и более эффективный способ или Replace () уже оптимизирован для этого?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
13
0
15 342
10
Перейти к ответу Данный вопрос помечен как решенный

Ответы 10

Ответ принят как подходящий

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

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

Я считаю, что они провели свой тест в PowerShell, что не относится к C#. В C3 управление памятью отличается от PowerShell, и он не преобразует StringBuilder в String для замены в нем символов. С другой стороны, RegEx и StringBuilder лучше работают с большими объемами данных, которые добавляются к ним кусками.

AaA 24.04.2013 11:38

RegEx - ужасный вариант для выполнения замены большого количества текста. Каким бы мощным он ни был, многие сторонники RegEx видят весь мир как гвоздь, а RegEx - как молоток. Для случаев использования большого количества текста см. FastReplacer stackoverflow.com/a/11442008/141172.

Eric J. 05.11.2014 20:57

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

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

Но для наивной реализации string.Replace подойдет.

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

Пришлось сделать что-то подобное недавно. Что я сделал:

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

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

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

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

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

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

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

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

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

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

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

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

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

FastReplacer is good for executing many Replace operations on a large string when performance is important.

The main idea is to avoid modifying existing text or allocating new memory every time a string is replaced.

We have designed FastReplacer to help us on a project where we had to generate a large text with a large number of append and replace operations. The first version of the application took 20 seconds to generate the text using StringBuilder. The second improved version that used the String class took 10 seconds. Then we implemented FastReplacer and the duration dropped to 0.1 seconds.

Это то, что я искал. Пожалуйста, проверьте таблицу скорости и попробуйте.

Marek Bar 05.11.2014 10:52

Другие вопросы по теме