Функция СтрШаблон с именованными маркерами

Функция позволяет задавать именованные маркеры формата [Имя], в отличии от типовых нумерованных формата %n

Преимущества по сравнению с типовой функцией СтрШаблон:
— Код вызова функции проще для восприятия за счет именованных маркеров и параметров.
— Устойчива к перестановкам параметров, к вставкам между параметрами, т.к. сопоставление выполняется по именам, а не по порядку.

Пример использования:

Текст = СтрШаблон_("Заказано товаров на сумму [Сумма] в количестве [Колво]",
"Сумма", 2500, "Колво", 100);

Функция:

Функция СтрШаблон_(Шаблон,
п11="", п12="", п21="", п22="", п31="", п32="", п41="", п42="", п51="", п52="",
п61="", п62="", п71="", п72="", п81="", п82="", п91="", п92="", п101="", п102="",
п111="", п112="", п121="", п122="", п131="", п132="", п141="", п142="", п151="", п152="") экспорт

Результат = Шаблон;

Для сч = 1 по 15 Цикл
ИмяПараметра = Вычислить("п"+сч+"1");
Маркер = "["+ИмяПараметра+"]";

Если ИмяПараметра = "" Тогда
Прервать;
ИначеЕсли СтрНайти(Результат, Маркер) = 0 Тогда
ВызватьИсключение СтрШаблон("Не найден маркер %1 в шаблоне ""%2""", Маркер, Шаблон);
Иначе
Результат = СтрЗаменить(Результат, Маркер, Вычислить("п"+сч+"2"));
КонецЕсли;

КонецЦикла;

// Лишние маркеры удаляем
Пока Истина Цикл
Начало = СтрНайти(Результат, "[");
Конец = СтрНайти(Результат, "]");

Если Начало=0 ИЛИ Конец=0 ИЛИ Начало>Конец Тогда
Прервать;
КонецЕсли;

Результат = Лев(Результат,Начало-1) + Сред(Результат,Конец+1);
КонецЦикла;

Возврат Результат;

КонецФункции

 

 

 Функция на RegExp (не нашел сценариев, где RegExp дал бы здесь прирост по сравнению с кодом 1С)

 

 

 Юнит-тесты под Vanessa-ADD 6.4.0

26 Comments

  1. WalterMort

    Однако в коде своего шаблона, автор использует платформенный СтрШаблон, хотя мог использовать и свой.

    Reply
  2. A.Sytchev

    А чем она лучше БСПшной СтроковыеФункцииКлиентСервер.ВставитьПараметрыВСтроку?

    https://www.screenpresso.com/=RXKZc

    Reply
  3. kirinalex

    (2) Читабельнее и не нужно создавать структуру.

    Для сравнения:

    СтрШаблон_(, «Имя»,»Вася», «Фамилия»,»Пупкин», «Город»,»Москва», «СемейноеПоложение»,»Все сложно»)
    
    Новый Структура(«Имя, Фамилия, Город, СемейноеПоложение», «Вася», «Пупкин», «Москва», «Все сложно»)
    Reply
  4. A.Sytchev

    (3) Насчет читабельности я бы поспорил.

    Параметры = Новый Структура;
    Параметры.Вставить(«Имя», «Вася»);
    Параметры.Вставить(«Фамилия»,  «Пупкин»);
    Параметры.Вставить(«Город»,  «Москва»);
    Параметры.Вставить(«СемейноеПоложение», «Все сложно»);
    

    А если мне надо 16 параметров?

    Reply
  5. kirinalex

    (4)

     СтрШаблон_(,
    «Имя», «Вася»,
    «Фамилия», «Пупкин»,
    «Город», «Москва»,
    «СемейноеПоложение», «Все сложно»)
    А если мне надо 16 параметров?

    Сложный вопрос. У меня нет на него ответа.

    Для справки — платформенный СтрШаблон допускает не больше 10ти параметров.

    А в индустрии разработки программирования шагнули намного дальше: https://python-scripts.com/string-formatting

    Reply
  6. kirinalex

    немного оптимизировал

    исправил ошибку в Тест_НеНайденМаркер

    Reply
  7. kirinalex

    (1) возникает нехороший эффект из за удаления лишних маркеров

    нужно будет экранирование квадратных скобок прикрутить

    Reply
  8. dhurricane

    Мне кажется, что прерывать цикл при первой встрече пустого имени параметра неудачная идея. Это усложнит применение функции для различных шаблонов строк, зависящих от некоторого условия, но при этом с примерно одинаковым набором параметров. Во встроенной функции «СтрШаблон» это как раз порой и раздражает — строгое соответствие списка маркеров списку параметров функции.

    Аналогично с удалением неиспользованных параметров. Разве не удобнее становится, когда забытый маркер бросается в глаза при выводе готовой строки?

    Reply
  9. kirinalex

    (9) Приведите пример кода когда прерывание при встрече пустого параметра будет неудобно.

    Аналогично с удалением неиспользованных параметров. Разве не удобнее становится, когда забытый маркер бросается в глаза при выводе готовой строки?

    Я исходил из предположения удобства, когда маркер оказался не нужен в конкретном случае. Так он удалится автоматически. И также работает платформенная СтрШаблон — просто удаляет маркер

    Reply
  10. v77

    Померил скорость велосипеда из (8). Работает в три раза быстрее и писанины в два раза меньше.

    Текст = СтрШаблон_(«Заказано товаров на сумму [Сумма] в количестве [Колво]»,
    «Сумма», 2500, «Колво», 100);
    
    Текст = Вычислить(F(«Заказано товаров на сумму {Сумма} в количестве {Колво}»));
    
    Reply
  11. dhurricane

    (10)

    Приведите пример кода когда прерывание при встрече пустого параметра будет неудобно.

    Не могу. 🙂 Пока получше думал над примерами, пришел к выводу, что во всех случаях для Вашей функции любая универсальность будет врагом читаемости.

    И также работает платформенная СтрШаблон — просто удаляет маркер

    Да, конечно. Я нахожу это неудобным, но это дело вкуса, безусловно.

    Я ошибся и на счет встроенной СтрШаблон. Поспешил, извините. Она не требует строго соответствия параметров маркерам. Только чтобы маркеров было не меньше, чем параметров функции. Аналогично и у Вас: лишние имена маркеров приведут к исключительной ситуации. Пару раз сталкивался с подобной особенностью, когда хотел написать что-то вроде такого:

    Если ЗначениеЗаполнено(Выборка.Склад) Тогда
    ТекстСообщения = НСтр(«ru = ‘Не хватает товара %1 в количестве %2 на складе %3′»);
    Иначе
    ТекстСообщения = НСтр(«ru = ‘Не хватает товара %1 в количестве %2′»);
    КонецЕсли;
    
    ТекстСообщения = СтрШаблон(ТекстСообщения,
    Выборка.Номенклатура,
    Выборка.Количество,
    Выборка.Склад);

    Показать

    И мне кажется такое поведения функции СтрШаблон также неудобным.

    Reply
  12. kirinalex

    (12)

    И также работает платформенная СтрШаблон — просто удаляет маркер

    Да, конечно. Я нахожу это неудобным, но это дело вкуса, безусловно.

    Эту реализация я в полной мере еще сам не оценил на практике и сделал так, чтобы у программиста не было потребности самому вычищать эти маркеры или составлять шаблон динамически, а также потому что в платформенной СтрШаблон сделано также. Есть несколько вариантов как сделать — пока остановился на этом.

    Если ЗначениеЗаполнено(Выборка.Склад) Тогда

    ТекстСообщения = НСтр(«ru = ‘Не хватает товара %1 в количестве %2 на складе %3′»);

    Иначе

    ТекстСообщения = НСтр(«ru = ‘Не хватает товара %1 в количестве %2′»);

    КонецЕсли;

    ТекстСообщения = СтрШаблон(ТекстСообщения,

    Выборка.Номенклатура,

    Выборка.Количество,

    Выборка.Склад);

    Показать

    Ну, лично я не пишу такие универсальные конструкции, не задаю параметры объектам если в них нет реальной потребности. В данном примере это Склад.

    Reply
  13. kirinalex

    (11)

    писанины в два раза меньше.

    где именно меньше?

    Reply
  14. kirinalex

    (8)

    СуммаДолга = 100500;

    Имя = «Петр Петрович»;

    ВВ = Вычислить(F(«Приветонище, {Имя}. Ваш долг {СуммаДолга} руб.»));

    А если СуммаДолга лежит в Выборке то нужно будет сделать так?

    СуммаДолга = Выборка.Сумма;

    Имя = «Петр Петрович»;

    ВВ = Вычислить(F(«Приветонище, {Имя}. Ваш долг {СуммаДолга} руб.»));

    Reply
  15. kirinalex

    (8)

    Функция F(Стр)

    Вы считаете что имя функции «F» это нормально? Она будет глобальной?

    Reply
  16. dhurricane

    (1) Кстати, действительно еще можно было бы сделать незамысловатую обертку для встроенной функции 🙂

    Функция СтрШаблон_(Знач Шаблон,
    п11=»», п12=»», п21=»», п22=»», п31=»», п32=»», п41=»», п42=»», п51=»», п52=»»,
    п61=»», п62=»», п71=»», п72=»», п81=»», п82=»», п91=»», п92=»», п101=»», п102=»») экспорт
    
    Шаблон = СтрЗаменить(Шаблон, «[«+п11+»]», «%1»);
    Шаблон = СтрЗаменить(Шаблон, «[«+п21+»]», «%2»);
    Шаблон = СтрЗаменить(Шаблон, «[«+п31+»]», «%3»);
    Шаблон = СтрЗаменить(Шаблон, «[«+п41+»]», «%4»);
    Шаблон = СтрЗаменить(Шаблон, «[«+п51+»]», «%5»);
    Шаблон = СтрЗаменить(Шаблон, «[«+п61+»]», «%6»);
    Шаблон = СтрЗаменить(Шаблон, «[«+п71+»]», «%7»);
    Шаблон = СтрЗаменить(Шаблон, «[«+п81+»]», «%8»);
    Шаблон = СтрЗаменить(Шаблон, «[«+п91+»]», «%9»);
    Шаблон = СтрЗаменить(Шаблон, «[«+п101+»]», «%10»);
    
    Возврат СтрШаблон(Шаблон, п12, п22, п32, п42, п52, п62, п72, п82, п92, п102);
    
    КонецФункции

    Показать

    Reply
  17. kirinalex

    (17) интересное решение, если не учитывать что в таком виде оно не работает)

    ну и если сделать его рабочим, что не трудно, то при несоответствии маркеров параметрам в результате получаем ошибку «Слишком много фактических параметров» — как говорится, разбирайся как хочешь)

    Reply
  18. v77

    (16) F или не F какая разница. Назовите как хотите.

    А если СуммаДолга лежит в Выборке то нужно будет сделать так?

    Ну так и писать {Выборка.Сумма}

    ВВ = Вычислить(F(«Приветонище, {Имя}. Ваш долг {Выборка.Сумма} руб.»));

    Reply
  19. dhurricane

    (18) Проклятье! Что-то много я сегодня невпопад пишу. Пожалуй, отойду на сегодня от клавиатуры подальше. 🙂

    Reply
  20. kirinalex

    (19) ну тогда удачи вам с такой замечательной функцией F

    Хотя вашу идею я запомню на всякий пожарный. Мысля у народа работает)

    Reply
  21. v77

    (21)

    Мысля у народа работает)

    А ты типа не народ 🙂

    Reply
  22. v77

    Кстати. Можно еще ускорить, если заранее шаблон заготовить

    Шаблон = F(«Приветонище, {Выборка.Наименование}. Ваш долг {Выборка.СуммаДолга} руб.»);
    Пока Выборка.Следующий() Цикл
    ВВ = Вычислить(Шаблон);
    Сообщить(ВВ);
    КонецЦикла;
    
    
    Reply
  23. kirinalex

    (23) Все таки, на написание функции меня сподвигла не оптимизация, а случаи нечитабельности больших шаблонов. Дискуссия получается полезная, но пока меня никто не убедил отказаться от своей реализации. Краткости кода я предпочитаю стабильность и читабельность.

    Reply
  24. v77

    (24) А моя то чем не читабельная. Очень даже читабельная. Да в добавок еще и быстрая. И кода меньше писать.

    Reply
  25. kirinalex

    (25) сама функция? Я бы не сказал что читабельная.

    И реализация точно не стабильная, т.к. не проверяется синтаксическим контролем.

    Reply
  26. v77

    (26) Ну функцию можно написать какую угодно. Тем более сейчас уже не важно как быстро она будет парсить шаблон, т.к. её в цикле можно не использовать.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *