Операция конкатенации 1с это
Во встроенном языке платформы 1С:Предприятие, как и во многих других языках программирования, присутствует возможность сложения строк. Это легко:
Когда же нужно из некоторой коллекции строк получить одну единую, то можно сделать в цикле:
Все это хорошо работает когда у нас немного данных. Но все кардинально меняется, когда счет строк идет на тысячи (обычное дело при работе с клиент-банками, веб-сервисами, КПК и в прочих ситуациях). Попробуйте и сами увидите как на глазах падает производительность. О резкой деградацию производительности при множественных конкатенациях уже писали. Даже на Инфостарте . .
Но водь нас больше всего интересуют практические решения. Варианты с внешними компонентами я даже не стал рассматривать. Нужно ведь писать код сразу так, что бы он работал кросплатформенно! Так же были проигнорированы варианты с записью в файл - нам лишние задержки от дисковой подсистемы совсем не нужны.
Некоторые предлагают очевидное в таком случае решение - использование текстового документа. С практической стороны необходимо отметить, что все составные строки в этом объекте идут отдельными строками. Т.е. воспользовавшись методом ПолучитьТекст() необходимо еще сделать замену переносов строк на пустую строку. В случае использования вами символа переноса строки в подстроках, необходимо предварительно сделать замену его на некоторую уникальную последовательность символов, а после получения результата произвести обратное преобразование.
Я же для себя изобрел собственный велосипед, который по скорости превзошел использование текстового документа. Все подстроки заносятся в массив, который перегоняется в текстовое представление с помощью ЗначениеВСтрокуВнутр(), а далее вычищается от "лишнего". Работает стабильно и довольно быстро. Подробности реализации можете посмотреть в прикрепленной обработке.
UPD 1. Из комментария узнал про новый способ конкатенирования - использование объекта ЗаписьXML. У него есть интересный метод ЗаписатьБезОбработки() для помещения уже готового документа в том виде, какой подается на вход, т.е. без лишних тегов.
Для того, что бы определить какой метод лучше (и стоило ли вообще заморачиваться) была написана маленькая обработка. Условия для всех равны - замер происходит в милисекундах от вызова серверной функции с реализацией соответствующего алгоритма до получения отклика. Что бы нивелировать случайные факторы, я проводил по четыре замера и выводил в таблицу среднее значение.
В результате я получил следующую таблицу:
В результате мы еще раз убедились в непрактичности использования обычной конкатенации на больших объемах строк. Как видно из получившегося графика зависимость скорости выполнения от количества элементов имеет экспоненциальный характер. В то время, как оба метода "обхода" стабильно показывают прямолинейную зависимость. Что позволяет нам прогнозировать общее время выполнения обработок связанных с обработкой текста. И мой метод превосходит по быстродействию использование текстового документа в 2 раза!
UPD 2. К сожалению не нашел в инфостартовском редакторе инструмента для редактирования количества столбцов таблицы и не увидел переключения в режим HTML-документа для правки руками. По результатам тестирования метода с ЗаписьXML получились результаты идентичные методу массивом как на малых, так и на больших наборах подстрок. Поэтому я отдаю этому методы лавры победителя - при прочих равных он легко запоминается и не содержит подводных камней.
Если нужно из некоторой коллекции строк получить одну единую, это можно сделать в цикле:
ИтогСтрока = Строка + ЭлементКоллекции;
Работа функции конкатенации не вызывает проблем с производительностью, когда обрабатывается небольшое количество данных. Производительность может упасть, когда счет строк идет на тысячи.
Есть несколько вариантов получения строки из коллекции.
Первый – с помощью текстового документа. В этом случае все составные части будут идти отдельными строками. При использовании функции ПолучитьТекст(), нужно будет сделать замену символов переноса строк в коде на пустую строку, а после получения результата использовать метод обратного преобразования.
Другой способ – занести все подстроки в массив, который преобразуется в текстовое представление с помощью функции ЗначениеВСтрокуВнутр(), а далее лишнее очищается.
При массовых операциях конкатенации строк можно использовать методы платформы СтрРазделить и СтрСоединить.
ИзвТекст= Новый Массив;
Для НомерКолонки = 1 По Макет.ШиринаТаблицы Цикл
ИзвТекст.Добавить(ТекстОбласти);
…
РезультатТекст = СтрСоединить(ИзвТекст, Символы.ПС);
Еще один способ операции конкатенации строк — использование объекта ЗаписьXML. У этого объекта можно использовать метод ЗаписатьБезОбработки() для «сборки» документа в том виде, какой подается на вход, т.е. без лишних тегов.
2. Конкатенация в запросах
При создании текстов запросов используя функцию конкатенации можно сделать запросы более гибкими.Конкатенация в запросах может использоваться при программной "сборке" текста запроса. Пример:
ТекстЗапроса =
"ВЫБРАТЬ
Номенклатура.Наименование КАК Наименование,
&ИмяПоляКод КАК КодНоменклатуры
ИЗ
Справочник.Номенклатура КАК Номенклатура ;
ТекстЗапроса = СтрЗаменить(ТекстЗапроса , "&ИмяПоляКод ", "Номенклатура." + ИмяПоляКод);
Пример изменения имени таблицы в запросе:
"ВЫБРАТЬ
|ТаблицаСправочника.Наименование КАК Наименование,
|ТаблицаСправочника.Код КАК КодСправочника
|ИЗ
|&ТабСправочника КАК ТаблицаСправочника";
ТекстЗапроса = СтрЗаменить(ТекстЗапроса , "&ТабСправочника", "Справочник." + ИмяСправочника);
Также к данной функции можно прибегнуть, когда нужно сложить части строки, чтобы результат мог потом стать проверяемым параметром.
Если нужно из некоторой коллекции строк получить одну единую, это можно сделать в цикле:
ИтогСтрока = Строка + ЭлементКоллекции;
Работа функции конкатенации не вызывает проблем с производительностью, когда обрабатывается небольшое количество данных. Производительность может упасть, когда счет строк идет на тысячи.
Есть несколько вариантов получения строки из коллекции.
Первый – с помощью текстового документа. В этом случае все составные части будут идти отдельными строками. При использовании функции ПолучитьТекст(), нужно будет сделать замену символов переноса строк в коде на пустую строку, а после получения результата использовать метод обратного преобразования.
Другой способ – занести все подстроки в массив, который преобразуется в текстовое представление с помощью функции ЗначениеВСтрокуВнутр(), а далее лишнее очищается.
При массовых операциях конкатенации строк можно использовать методы платформы СтрРазделить и СтрСоединить.
ИзвТекст= Новый Массив;
Для НомерКолонки = 1 По Макет.ШиринаТаблицы Цикл
ИзвТекст.Добавить(ТекстОбласти);
…
РезультатТекст = СтрСоединить(ИзвТекст, Символы.ПС);
Еще один способ операции конкатенации строк — использование объекта ЗаписьXML. У этого объекта можно использовать метод ЗаписатьБезОбработки() для «сборки» документа в том виде, какой подается на вход, т.е. без лишних тегов.
2. Конкатенация в запросах
При создании текстов запросов используя функцию конкатенации можно сделать запросы более гибкими.Конкатенация в запросах может использоваться при программной "сборке" текста запроса. Пример:
ТекстЗапроса =
"ВЫБРАТЬ
Номенклатура.Наименование КАК Наименование,
&ИмяПоляКод КАК КодНоменклатуры
ИЗ
Справочник.Номенклатура КАК Номенклатура ;
ТекстЗапроса = СтрЗаменить(ТекстЗапроса , "&ИмяПоляКод ", "Номенклатура." + ИмяПоляКод);
Пример изменения имени таблицы в запросе:
"ВЫБРАТЬ
|ТаблицаСправочника.Наименование КАК Наименование,
|ТаблицаСправочника.Код КАК КодСправочника
|ИЗ
|&ТабСправочника КАК ТаблицаСправочника";
ТекстЗапроса = СтрЗаменить(ТекстЗапроса , "&ТабСправочника", "Справочник." + ИмяСправочника);
Также к данной функции можно прибегнуть, когда нужно сложить части строки, чтобы результат мог потом стать проверяемым параметром.
Практики использования типовых и самописных конфигураций 1С иногда сталкиваются с "торможениями" продуктов. Причины могут быть разными - некоторые любит делать множественные обращения через точку в циклах, другие используют вложенные запросы в параметрах виртуальных таблиц, третьи бессмысленно гоняют мегабайты контекста в клиент-серверной модели. Но иногда можно получить огромную потерю производительности на банальной операции сложения строк. Давайте рассмотрим эту ситуацию детальнее.
Странно, но в статье Опять двойка , на которую автор ссылается, уже приводился предлагаемый здесь метод. Даже код уже был приведен(1) ildarovich, все возможно. Но финт со ЗначениеВСтрокуВнутр() я придумал для своей обработки работы с веб-сервисом, которая до этого очень медленно работала. После этого я решил сравнить её быстродействие с "классикой" и способом, который нашел на партнерском форуме. А уже затем я решил поделится с общественностью своей наработкой. Про статью "Опять двойка" узнал в процессе верстки своей, так же как и про другие отдаленно похожие заметки (на других ресурсах). От мысли писать свою статью я не отказывался по причинам: она оригинальная, не повторяет чужих идей, приведены конкретные цифры замеров производительности в то время, когда другие лишь мимолетом упоминали про свои субъективные ощущения.
Раз существует более "навороченный" вариант с ЗаписьXML, то конечно стоит его рассмотреть и добавить в табличку сравнения быстродействия. Я думал и про этот объект, но не знал про его любопытный метод ЗаписатьБезОбработки() и потому не стал рассматривать. А вот от использования указанной в комменте реализации составления строки из массива я бы рекомендовал воздержаться - в ней есть баг, который я у себя дополнительно обошел (хотя в некоторых случаях искажение содержимого роли не играет и потому некоторым может подойти).
(1) ildarovich, про 12% - полное вранье . Добавил в обработку тестирование ЗаписиXML - результаты сопоставимы с методом массива почти на 99%. Так на формирование строки из 50000 подстрок методом массива уходит 1466 милисекунда, а с помощью ЗаписиXML - 1474. При работе со 100000 подстрок результаты - 2906 и 2985. Единственное преимущество - элегантность кода и отсутствие шаманства. (1) ЗначениеВСтрокуВнутр - ошибочно излишне обрезает строку справа, в некоторых вариантах тестов.Видимо вместо Массив.Количество() - надо что-то другое.. Разбираться не было времени, решил использовать ЗаписьXML. Статья и обработка обновлены четвертым способом конкатенирования строк. (5) infostart user, это не способ, а всего лишь анонс будущей функциональности. Как показывает практика, самый короткий промежуток между заметкой в зазеркалье и получением тестовой сборки платформы равен полугоду. Скорее всего добавят в 8.3.6
Функция форматирования СтрШаблон()
Функция работы со строками СтрСравнить()
Функции работы со строками СтрНачинаетсяС(), СтрЗаканчиваетсяНа()
Функции работы со строками СтрРазделить(), СтрСоединить()
Функция работы со строками СтрНайти()
(7) Улугбек, а на заборе написано, что Цой жив. И еще много чего тоже написано.
А попробуйте зайти в конфигуратор и воспользоваться этими функциями!
Подсказка: в ЗАЗЕРКАЛЬЕ пишут разработчики платформы о новых фичах, которые они у себя разрабатывают. Это не место для официальных пресс-релизов, а всего лишь блог. После разработки пройдет еще цикл тестирования и по результатам примут решение, когда переносить их в рабочие сборки.
Читайте также: