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

Функция позволяет задавать именованные маркеры формата [Имя], в отличии от типовых нумерованных формата %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 не будет опубликован. Обязательные поля помечены *