Как сравнить и объединить два массива или таблицы значений в 1С при соблюдении условий по колонкам

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

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

Анализ исходных данных и терминологии

Прежде всего, проанализируем структуру данных. В среде 1С классический объект Массив не имеет колонок. Если речь идет о «столбцах», мы имеем дело либо с объектом ТаблицаЗначений, либо с массивом, элементами которого являются объекты Структура. Это крайне важно, так как методы работы с этими объектами различаются.

Условие задачи:

  1. Количество «столбцов» в обеих коллекциях совпадает.
  2. Один конкретный столбец во втором массиве должен быть пустым.
  3. Все остальные столбцы в соответствующих строках должны быть идентичны.
  4. При выполнении условий данные объединяются.

Способ 1. Программный перебор элементов в цикле

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

Для реализации нам потребуется вложенный цикл: внешний проходит по строкам, а внутренний — по ключам (колонкам) структур. Проанализируем пример кода:


// Предположим, Массив1 и Массив2 уже заполнены данными
МассивыРавны = Истина;
ИмяПустойКолонки = "НужноеПоле"; // Имя колонки, которая во 2-м массиве должна быть пустой

Если Массив1.Количество() <> Массив2.Количество() Тогда
    МассивыРавны = Ложь;
Иначе
    Для Индекс = 0 По Массив1.Количество() - 1 Цикл
        Строка1 = Массив1[Индекс];
        Строка2 = Массив2[Индекс];
        
        Для Каждого ЭлементСтруктуры Из Строка1 Цикл
            Ключ = ЭлементСтруктуры.Ключ;
            Значение1 = ЭлементСтруктуры.Значение;
            Значение2 = Строка2[Ключ];
            
            Если Ключ = ИмяПустойКолонки Тогда
                // Проверяем, что во втором массиве это поле пустое
                Если ЗначениеЗаполнено(Значение2) Тогда
                    МассивыРавны = Ложь;
                    Прервать;
                КонецЕсли;
            Иначе
                // Проверяем совпадение остальных данных
                Если Значение1 <> Значение2 Тогда
                    МассивыРавны = Ложь;
                    Прервать;
                КонецЕсли;
            КонецЕсли;
        КонецЦикла;
        
        Если Не МассивыРавны Тогда
            Прервать;
        КонецЕсли;
    КонецЦикла;
КонецЕсли;

Если МассивыРавны Тогда
    // Логика объединения: например, создание новой таблицы или дополнение первой
    ПоказатьПредупреждение(, "Условия пройдены, массивы объединены.");
КонецЕсли;

В данном коде мы используем функцию ЗначениеЗаполнено(), которая является универсальным инструментом 1С для проверки пустых ссылок, строк, нулевых чисел и дат.

Способ 2. Использование механизмов запросов (оптимально для больших данных)

Если данные представлены в виде таблиц значений, наиболее производительным методом будет использование временных таблиц в запросе. Рассмотрим подробнее, почему это эффективно: механизм СУБД выполняет операции соединения и фильтрации гораздо быстрее, чем интерпретатор встроенного языка.

Разберем этапы этого метода:

  1. Выгружаем обе таблицы в менеджер временных таблиц.
  2. Выполняем ВНУТРЕННЕЕ СОЕДИНЕНИЕ по всем полям, которые должны совпадать.
  3. В условии ГДЕ прописываем проверку на пустое значение целевой колонки.
  4. Используем оператор ОБЪЕДИНИТЬ ВСЕ для формирования итогового результата.

Проанализируем пример текста запроса:


ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_Первая ИЗ &ТЗ1 КАК ТЗ1;
ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_Вторая ИЗ &ТЗ2 КАК ТЗ2;

ВЫБРАТЬ
    Т1.Колонка1,
    Т1.Колонка2,
    Т1.ПустаяКолонка
ИЗ
    ВТ_Первая КАК Т1
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_Вторая КАК Т2
    ПО Т1.Колонка1 = Т2.Колонка1
    И Т1.Колонка2 = Т2.Колонка2
ГДЕ
    (Т2.ПустаяКолонка ЕСТЬ NULL ИЛИ Т2.ПустаяКолонка = &ПустоеЗначение)

Этот подход гарантирует, что вы получите только те строки, которые соответствуют условию «совпадения всех полей, кроме одного пустого».

Способ 3. Индексирование и метод НайтиСтроки()

Если мы работаем с объектом ТаблицаЗначений, мы можем значительно ускорить поиск, создав индексы. Рассмотрим ситуацию: нам нужно проверить, есть ли во второй таблице строка, соответствующая первой. Посмотрим на алгоритм:

  1. Добавим индексы в Таблица2 по всем проверяемым колонкам.
  2. Создадим структуру отбора.
  3. Используем метод НайтиСтроки().

// Индексация для ускорения
Таблица2.Индексы.Добавить("Колонка1, Колонка2");

Для Каждого Строка1 Из Таблица1 Цикл
    Отбор = Новый Структура;
    Отбор.Вставить("Колонка1", Строка1.Колонка1);
    Отбор.Вставить("Колонка2", Строка1.Колонка2);
    
    НайденныеСтроки = Таблица2.НайтиСтроки(Отбор);
    
    Для Каждого СтрокаПоиска Из НайденныеСтроки Цикл
        Если Не ЗначениеЗаполнено(СтрокаПоиска.ПустаяКолонка) Тогда
            // Условие выполнено
        КонецЕсли;
    КонецЦикла;
КонецЦикла;

Способ 4. Сериализация в JSON (быстрый «лайфхак»)

Существует нестандартный, но быстрый способ сравнить две структуры или строки таблиц на полную идентичность. Мы можем временно очистить «пустую колонку» в обеих коллекциях и преобразовать их в строку JSON. Если полученные строки идентичны — значит, данные в коллекциях полностью совпадают.

Выясним причину популярности этого метода: он избавляет от необходимости писать длинные блоки Если...ИначеЕсли для каждого поля. Достаточно использовать ЗаписьJSON и просто сравнить две строки. Однако стоит помнить, что порядок ключей в структуре при сериализации должен быть одинаковым.

Объединение данных

После того как проверка пройдена, необходимо объединить коллекции. Рассмотрим два варианта объединения:

  1. Вертикальное объединение (дополнение): Если нужно просто добавить строки из второй таблицы в первую. Используется метод Добавить() в цикле или прямое копирование, если структуры колонок идентичны.
  2. Горизонтальное слияние: Если нужно перенести значения из колонок второй таблицы в соответствующие строки первой таблицы. Для этого удобно использовать метод ЗаполнитьЗначенияСвойств(Приемник, Источник).

Подводя итог, выбор метода зависит от объема данных. Для небольших массивов в памяти идеально подойдет перебор в цикле с проверкой через ЗначениеЗаполнено(). Для обработки больших массивов данных из базы лучше всего использовать запросы с временными таблицами. Использование правильных инструментов 1С позволит избежать ошибок при сравнении типов и обеспечит высокую скорость работы вашей обработки.

← На главную