Как реализовать поиск всех комбинаций значений из многомерного массива в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке алгоритмов на 1С часто возникает задача, требующая перебора всех возможных комбинаций элементов из нескольких списков. Математически это называется декартовым произведением. На практике это нужно, например, при генерации всех вариантов комплектаций товаров, сочетаний характеристик или подборе графиков. Давайте разберем, как эффективно решить эту задачу, избегая избыточного использования рекурсии.

Понимание задачи

Представьте, что у нас есть три массива: в первом варианты 1.1, 1.2, 1.3; во втором — 2.1, 2.2, 2.3; в третьем — 3.1, 3.2. Нам нужно получить полный список всех возможных «кортежей», где первый элемент берется из первого массива, второй — из второго и так далее. Количество вариантов при этом растет экспоненциально, поэтому важно выбрать оптимальный алгоритм.

Итеративный подход к решению

Вместо использования глубокой рекурсии, которая может быть ресурсозатратной, мы можем воспользоваться методом «счетчика индексов». Суть подхода заключается в поддержании массива текущих индексов, который ведет себя как обычное число в системе счисления, где «разряды» имеют разное основание (длину каждого вложенного массива).

Рассмотрим по шагам, как реализовать этот алгоритм:

  1. Создаем массив Индексы, длина которого совпадает с количеством наших массивов. Изначально заполняем его нулями.
  2. В цикле Пока собираем текущую комбинацию, обращаясь к элементам массивов по текущим индексам.
  3. Вызываем вспомогательную процедуру для обновления индексов: увеличиваем последний индекс на единицу. Если он достигает размера своего массива, мы обнуляем его и передаем «перенос» на индекс слева.
  4. Если перенос доходит до первого элемента и тот тоже требует сброса, значит, все комбинации перебраны.

Пример кода реализации

Рассмотрим подробнее реализацию на 1С. Основной код выглядит следующим образом:


&НаКлиенте
Процедура ВывестиРезультат(Команда)
    // Подготовка исходных данных
    ВсеМассивы = Новый Массив;
    // ... здесь логика заполнения массивов ...
    
    // Инициализация счетчика индексов
    Индексы = Новый Массив;
    Для Сч = 1 По ВсеМассивы.Количество() Цикл
        Индексы.Добавить(0);
    КонецЦикла;
    
    Пока Истина Цикл
        ВывестиСообщение(ВсеМассивы, Индексы);
        Если НЕ УвеличитьИндекс(ВсеМассивы, Индексы) Тогда
            Прервать;
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Теперь разберем функцию, которая управляет перебором индексов:


&НаКлиенте
Функция УвеличитьИндекс(Массивы, Индексы)
    Результат = Ложь;
    Для Сч = Индексы.Количество() - 1 По 0 Цикл
        Индексы[Сч] = Индексы[Сч] + 1;
        Если Индексы[Сч] < Массивы[Сч].Количество() Тогда
            Результат = Истина;
            Прервать;
        Иначе
            Индексы[Сч] = 0;
        КонецЕсли;
    КонецЦикла;
    Возврат Результат;
КонецФункции

Почему этот метод эффективен?

Данный алгоритм позволяет работать с большими объемами данных, так как мы не храним весь результирующий массив в памяти (что могло бы привести к ошибке нехватки памяти при большом количестве комбинаций). Вместо этого мы используем подход «генератора»: получаем одну комбинацию, обрабатываем её и переходим к следующей.

Важные рекомендации:

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

← На главную