При решении задач комбинаторики в 1С часто возникает ситуация, когда заранее неизвестно, сколько вложенных циклов потребуется. Проанализируем типичную ситуацию: на форме динамически генерируются элементы, где пользователь задает интервалы (значения «От», «До» и «Шаг»). Нам необходимо перебрать все возможные комбинации этих интервалов. Разберем по шагам, какие методы лучше использовать для этой задачи, и выясним причину, по которой некоторые популярные подходы могут оказаться губительными для системы.
Первая мысль, которая часто приходит в голову — сгенерировать текст кода с нужным количеством циклов в виде строки и запустить его с помощью Выполнить(). Рассмотрим подробнее, почему от этого подхода лучше отказаться:
Выполнить(), скрыв истинное место сбоя.Второй популярный подход — рекурсия. Функция вызывает саму себя для каждого следующего интервала, тем самым погружаясь вглубь на нужное количество уровней. Посмотрим на подводные камни этого метода:
Как справедливо отмечено в обсуждениях, любую рекурсию можно заменить циклом со стеком. Для генерации комбинаций множеств применяется алгоритм, работающий по принципу автомобильного одометра.
Разберем логику его работы:
Пока.Этот подход является наиболее сбалансированным с точки зрения архитектуры: он полностью исключает риск переполнения стека рекурсии и не требует динамической компиляции кода.
Еще один мощный и красивый инструмент 1С — перенос тяжелой комбинаторной математики на уровень СУБД. Проанализируем, как сгенерировать все варианты в запросе:
ИЗ без указания условий связи.Преимущества очевидны: движки баз данных идеально оптимизированы для выполнения соединений таблиц, поэтому вы быстро получите плоскую выборку всех возможных комбинаций.
Вне зависимости от того, какой метод вы выберете, мы совместно должны учитывать фундаментальную проблему математики — комбинаторный взрыв. Перемножение множества интервалов ведет к экспоненциальному росту количества итераций.
Если мы попытаемся сохранить результат сразу всех пересечений в одну таблицу значений или массив, клиентское приложение 1С может просто зависнуть из-за исчерпания доступной оперативной памяти (Out of Memory). В таких тяжелых задачах настоятельно рекомендуется обрабатывать данные «на лету», порциями, внутри самой последней итерации, не сохраняя весь объем промежуточных комбинаций в память.