Разработка и Конфигурация · 12 мин
Как сравнить два массива в 1С
Как сравнить два массива в 1С: перебор в цикле, Найти, ВГраница, сравнение по значениям и порядку. Готовые функции с кодом, типичные ошибки и FAQ.
Сравнение двух массивов — типовая задача при разработке на платформе 1С:Предприятие: проверка изменений в табличной части документа, поиск расхождений между старыми и новыми наборами данных, контроль дублей. Встроенной функции «сравнить массивы» в языке нет, поэтому задачу решают комбинацией методов Найти, Количество, ВГраница и циклов.
Важно сразу определить, что именно требуется: проверить полное совпадение массивов (те же элементы в том же порядке), найти элементы, которых нет в одном из массивов, или получить пересечение. Для каждой из этих задач подходит свой алгоритм, и они не взаимозаменяемы.
Ниже приведены рабочие варианты кода, которые можно перенести в общий модуль конфигурации, а также ограничения каждого подхода и типичные ошибки.
Определите, какое сравнение вам нужно
Прежде чем писать код, зафиксируйте постановку задачи. От неё зависит и алгоритм, и результат:
- Полное совпадение — массивы содержат одинаковые элементы в одинаковом порядке. Признак результата: функция возвращает Истина/Ложь.
- Совпадение по составу — элементы те же, но порядок не важен.
- Разность — какие элементы есть в первом массиве, но отсутствуют во втором (и наоборот).
- Пересечение — какие элементы присутствуют в обоих массивах.
Отдельно учтите тип элементов. Простые типы (число, строка, дата, булево) сравниваются оператором = напрямую. Ссылки на объекты базы сравниваются корректно — равенство ссылок означает один и тот же объект. А вот структуры, таблицы значений и другие составные объекты оператором = по содержимому не сравнишь: сравнивается ссылка на объект, а не его наполнение.
Проверка полного совпадения массивов
Классический вариант: сначала сравниваем количество элементов, затем в цикле — элементы по индексам. Если длины различаются, массивы точно не равны, и цикл не нужен.
Функция МассивыРавны(Массив1, Массив2) Экспорт
Если Массив1.Количество() <> Массив2.Количество() Тогда
Возврат Ложь;
КонецЕсли;
Для Индекс = 0 По Массив1.ВГраница() Цикл
Если Массив1[Индекс] <> Массив2[Индекс] Тогда
Возврат Ложь;
КонецЕсли;
КонецЦикла;
Возврат Истина;
КонецФункции
Функция возвращает Истина, только если длины равны и каждый элемент первого массива равен элементу второго с тем же индексом. Это строгое сравнение с учётом порядка.
Обратите внимание на метод ВГраница() — он возвращает индекс последнего элемента (на единицу меньше количества). Цикл «Для Индекс = 0 По Массив1.ВГраница()» корректно пройдёт все элементы, включая последний. Если массив пуст, ВГраница() вернёт -1, и цикл не выполнится ни разу — два пустых массива будут признаны равными, что обычно и требуется.
Сравнение по составу без учёта порядка
Если порядок элементов не важен, сравнение по индексам не подходит: массивы (1, 2, 3) и (3, 2, 1) будут признаны разными, хотя состав одинаков. Здесь два рабочих подхода.
Первый — отсортировать копии массивов и сравнить по индексам. Для сортировки массива простых типов можно выгрузить его в список значений и вызвать СортироватьПоЗначению(), затем выгрузить обратно.
Второй — проверить вхождение каждого элемента первого массива во второй методом Найти, плюс контроль длин:
Функция СоставыСовпадают(Массив1, Массив2)
Если Массив1.Количество() <> Массив2.Количество() Тогда
Возврат Ложь;
КонецЕсли;
Для Каждого Элемент Из Массив1 Цикл
Если Массив2.Найти(Элемент) = Неопределено Тогда
Возврат Ложь;
КонецЕсли;
КонецЦикла;
Возврат Истина;
КонецФункции
У этого варианта есть тонкость: метод Найти не учитывает кратность элементов. Массивы (1, 1, 2) и (1, 2, 2) пройдут проверку, хотя состав строго не совпадает. Если дубликаты возможны и важны, используйте сортировку и сравнение по индексам или подсчёт вхождений через соответствие.
Поиск различий: что есть в одном массиве и чего нет в другом
Частая практическая задача — получить массив расхождений, например список товаров, которые удалили из табличной части, и список добавленных. Решается двумя проходами с методом Найти:
Функция РазностьМассивов(Массив1, Массив2) Экспорт
// Элементы, которые есть в Массив1, но отсутствуют в Массив2
Результат = Новый Массив;
Для Каждого Элемент Из Массив1 Цикл
Если Массив2.Найти(Элемент) = Неопределено Тогда
Результат.Добавить(Элемент);
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Чтобы получить полную картину изменений, вызовите функцию дважды: Удалённые = РазностьМассивов(СтарыйМассив, НовыйМассив) и Добавленные = РазностьМассивов(НовыйМассив, СтарыйМассив). Элементы, присутствующие в обоих массивах, в результат не попадут.
Пересечение (общие элементы) получается зеркальным условием: добавлять элемент в результат, если Массив2.Найти(Элемент) <> Неопределено. Если в исходных массивах есть дубликаты и в результате они не нужны, перед добавлением проверяйте Результат.Найти(Элемент) = Неопределено.
- 1Определите тип сравнения: полное совпадение, совпадение состава, разность или пересечение
- 2Проверьте типы элементов: простые типы и ссылки сравнивайте оператором =, составные объекты — по ключевым полям
- 3Сравните количество элементов — при полном совпадении разная длина сразу даёт отрицательный результат
- 4Выполните цикл с Найти() или сравнением по индексам в зависимости от задачи
- 5Проверьте результат на тестовых данных: равные массивы, разная длина, дубликаты, пустые массивы
Оптимизация для больших массивов
Метод Найти выполняет линейный поиск, поэтому цикл «для каждого элемента — Найти в другом массиве» на больших объёмах работает медленно. Когда массивы содержат тысячи и десятки тысяч элементов, применяйте одну из двух замен.
Первый вариант — соответствие. Выгрузите второй массив в соответствие (ключ — элемент, значение — что угодно, например Истина), затем проверяйте наличие элемента через Соответствие[Элемент] = Неопределено. Поиск в соответствии выполняется быстро, и общее время растёт почти линейно.
Функция РазностьЧерезСоответствие(Массив1, Массив2)
Индекс = Новый Соответствие;
Для Каждого Элемент Из Массив2 Цикл
Индекс.Вставить(Элемент, Истина);
КонецЦикла;
Результат = Новый Массив;
Для Каждого Элемент Из Массив1 Цикл
Если Индекс[Элемент] = Неопределено Тогда
Результат.Добавить(Элемент);
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Второй вариант — запрос. Выгрузите оба массива в таблицы значений, поместите их во временные таблицы и напишите запрос с полным соединением: расхождения видны по записям, где одна из сторон NULL. Это удобно, когда элементы составные (несколько полей) и данные уже лежат в таблицах значений.
Сравнение подходов
Простой и читаемый код; подходит для массивов до нескольких тысяч элементов. На больших объёмах работает медленно из-за линейного поиска.
Быстрый поиск элементов, хорош для больших массивов. Требует, чтобы элементы были допустимыми ключами соответствия, и не сохраняет порядок.
Оптимален для составных элементов и больших объёмов, позволяет сравнивать по нескольким полям. Требует выгрузки в таблицы значений и написания запроса.
Сравнение массивов со структурами и составными элементами
Если элементы массива — структуры (например, строки данных с полями «Номенклатура» и «Количество»), оператор = для них бессмыслен: две структуры с одинаковым наполнением не равны друг другу как объекты. Метод Найти по структуре тоже не найдёт другой экземпляр с теми же значениями.
Практические варианты:
- Сравнивать по ключевому полю: в цикле искать элемент второго массива с тем же значением ключа (например, той же номенклатурой), затем сравнивать остальные поля.
- Формировать строковый ключ из значимых полей («Номенклатура|Количество») и сравнивать массивы таких ключей обычными способами.
- Переложить данные в таблицы значений и использовать
Таблица.Найти(Значение, "Колонка")или запрос с соединением.
Выбор зависит от объёма и числа полей. Для пары полей и сотен строк достаточно строкового ключа; для сложных структур и больших объёмов надёжнее таблицы значений с запросом.
Проверка результата и отладка
После написания функции прогоните её на контрольных наборах: два одинаковых массива, массивы разной длины, массивы с переставленными элементами, массивы с дубликатами, пустые массивы, массивы со значением Неопределено. Каждый случай должен дать ожидаемый результат.
Для быстрой проверки удобно выводить содержимое массивов через Сообщить или в табличный документ. Если сравниваются ссылки, выводите представление и уникальный идентификатор — визуально одинаковые наименования могут принадлежать разным объектам, и это частая причина «ложных» расхождений.
Отдельно проверьте поведение с Неопределено: сравнение Элемент = Неопределено работает корректно, но Найти(Неопределено) найдёт элемент только если он действительно равен Неопределено. Смешение пустых строк, нулей и Неопределено в данных — источник трудноуловимых расхождений.
Как проверить результат
Функция полного совпадения возвращает Истина
Возвращает Ложь — проверьте типы элементов и порядок
Сразу Ложь без входа в цикл
Ошибка выхода за границы массива — значит, длина не проверяется
Результат соответствует принятому решению о кратности
(1,1,2) и (1,2,2) признаются равными, хотя не должны
Расхождения только при реально разных объектах
Ложные расхождения из-за разных экземпляров составных объектов
Часто задаваемые вопросы
Можно ли сравнить два массива одной строкой в 1С?
Нет, встроенной функции сравнения массивов по содержимому нет. Оператор = сравнивает ссылки на объекты, а не элементы. Минимальное решение — функция из нескольких строк: проверка количества и цикл сравнения по индексам.
Как сравнить массивы, если порядок элементов не важен?
Проверьте равенство длин, затем для каждого элемента первого массива вызовите Найти() во втором. Если возможны дубликаты и их кратность важна, сначала отсортируйте оба массива (например, через список значений) и сравните по индексам.
Как найти элементы, которые есть только в одном из массивов?
Пройдите циклом по первому массиву и добавляйте в результат элементы, для которых Массив2.Найти(Элемент) вернул Неопределено. Повторите в обратную сторону, чтобы получить расхождения с обеих сторон.
Почему сравнение больших массивов работает медленно?
Метод Найти выполняет линейный перебор, поэтому цикл с Найти внутри даёт квадратичное время. Замените второй массив соответствием и проверяйте наличие через Соответствие[Элемент], либо используйте запрос по временным таблицам.
Как сравнить массивы структур?
Оператор = и Найти для структур по содержимому не работают. Сравнивайте по ключевому полю, формируйте строковый ключ из значимых полей или переносите данные в таблицы значений и сравнивайте запросом.
Что вернёт ВГраница() для пустого массива?
Минус один. Цикл «Для Индекс = 0 По Массив.ВГраница()» в этом случае не выполнится ни разу, поэтому два пустых массива корректно признаются равными без дополнительных проверок.
Что важно запомнить
Массивы в 1С сравнивают в коде: по длине и элементам по индексам — для полного совпадения, через Найти() — для разности и пересечения. Для больших объёмов используйте соответствие или запрос, а составные элементы сравнивайте по ключевым полям, а не оператором =.