К статье
Практический материал

Разработка и Конфигурация · 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. 1
    Определите тип сравнения: полное совпадение, совпадение состава, разность или пересечение
  2. 2
    Проверьте типы элементов: простые типы и ссылки сравнивайте оператором =, составные объекты — по ключевым полям
  3. 3
    Сравните количество элементов — при полном совпадении разная длина сразу даёт отрицательный результат
  4. 4
    Выполните цикл с Найти() или сравнением по индексам в зависимости от задачи
  5. 5
    Проверьте результат на тестовых данных: равные массивы, разная длина, дубликаты, пустые массивы

Оптимизация для больших массивов

Метод Найти выполняет линейный поиск, поэтому цикл «для каждого элемента — Найти в другом массиве» на больших объёмах работает медленно. Когда массивы содержат тысячи и десятки тысяч элементов, применяйте одну из двух замен.

Первый вариант — соответствие. Выгрузите второй массив в соответствие (ключ — элемент, значение — что угодно, например Истина), затем проверяйте наличие элемента через Соответствие[Элемент] = Неопределено. Поиск в соответствии выполняется быстро, и общее время растёт почти линейно.

Функция РазностьЧерезСоответствие(Массив1, Массив2)

Индекс = Новый Соответствие;

Для Каждого Элемент Из Массив2 Цикл

Индекс.Вставить(Элемент, Истина);

КонецЦикла;

Результат = Новый Массив;

Для Каждого Элемент Из Массив1 Цикл

Если Индекс[Элемент] = Неопределено Тогда

Результат.Добавить(Элемент);

КонецЕсли;

КонецЦикла;

Возврат Результат;

КонецФункции

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

Сравнение подходов

Цикл + Найти()

Простой и читаемый код; подходит для массивов до нескольких тысяч элементов. На больших объёмах работает медленно из-за линейного поиска.

Соответствие как индекс

Быстрый поиск элементов, хорош для больших массивов. Требует, чтобы элементы были допустимыми ключами соответствия, и не сохраняет порядок.

Запрос по временным таблицам

Оптимален для составных элементов и больших объёмов, позволяет сравнивать по нескольким полям. Требует выгрузки в таблицы значений и написания запроса.

Сравнение массивов со структурами и составными элементами

Если элементы массива — структуры (например, строки данных с полями «Номенклатура» и «Количество»), оператор = для них бессмыслен: две структуры с одинаковым наполнением не равны друг другу как объекты. Метод Найти по структуре тоже не найдёт другой экземпляр с теми же значениями.

Практические варианты:

  • Сравнивать по ключевому полю: в цикле искать элемент второго массива с тем же значением ключа (например, той же номенклатурой), затем сравнивать остальные поля.
  • Формировать строковый ключ из значимых полей («Номенклатура|Количество») и сравнивать массивы таких ключей обычными способами.
  • Переложить данные в таблицы значений и использовать Таблица.Найти(Значение, "Колонка") или запрос с соединением.

Выбор зависит от объёма и числа полей. Для пары полей и сотен строк достаточно строкового ключа; для сложных структур и больших объёмов надёжнее таблицы значений с запросом.

Типичные ошибки
01
Сравнение массивов оператором = : проверяется идентичность объекта, а не содержимое, результат почти всегда Ложь
02
Цикл «По Массив.Количество()» вместо ВГраница(): обращение по индексу, равному количеству, вызывает ошибку выхода за границы массива
03
Игнорирование дубликатов: Найти() не учитывает кратность, массивы (1,1,2) и (1,2,2) ошибочно признаются совпадающими
04
Сравнение структур и таблиц значений оператором = : сравниваются ссылки на объекты, а не их поля
05
Вложенный перебор на больших массивах: квадратичный рост времени, код «зависает» на рабочих данных

Проверка результата и отладка

После написания функции прогоните её на контрольных наборах: два одинаковых массива, массивы разной длины, массивы с переставленными элементами, массивы с дубликатами, пустые массивы, массивы со значением Неопределено. Каждый случай должен дать ожидаемый результат.

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

Отдельно проверьте поведение с Неопределено: сравнение Элемент = Неопределено работает корректно, но Найти(Неопределено) найдёт элемент только если он действительно равен Неопределено. Смешение пустых строк, нулей и Неопределено в данных — источник трудноуловимых расхождений.

Контрольные точки

Как проверить результат

Одинаковые массивы
Норма

Функция полного совпадения возвращает Истина

Тревожный признак

Возвращает Ложь — проверьте типы элементов и порядок

Массивы разной длины
Норма

Сразу Ложь без входа в цикл

Тревожный признак

Ошибка выхода за границы массива — значит, длина не проверяется

Массивы с дубликатами
Норма

Результат соответствует принятому решению о кратности

Тревожный признак

(1,1,2) и (1,2,2) признаются равными, хотя не должны

Ссылки на объекты
Норма

Расхождения только при реально разных объектах

Тревожный признак

Ложные расхождения из-за разных экземпляров составных объектов

Часто задаваемые вопросы

Можно ли сравнить два массива одной строкой в 1С?

Нет, встроенной функции сравнения массивов по содержимому нет. Оператор = сравнивает ссылки на объекты, а не элементы. Минимальное решение — функция из нескольких строк: проверка количества и цикл сравнения по индексам.

Как сравнить массивы, если порядок элементов не важен?

Проверьте равенство длин, затем для каждого элемента первого массива вызовите Найти() во втором. Если возможны дубликаты и их кратность важна, сначала отсортируйте оба массива (например, через список значений) и сравните по индексам.

Как найти элементы, которые есть только в одном из массивов?

Пройдите циклом по первому массиву и добавляйте в результат элементы, для которых Массив2.Найти(Элемент) вернул Неопределено. Повторите в обратную сторону, чтобы получить расхождения с обеих сторон.

Почему сравнение больших массивов работает медленно?

Метод Найти выполняет линейный перебор, поэтому цикл с Найти внутри даёт квадратичное время. Замените второй массив соответствием и проверяйте наличие через Соответствие[Элемент], либо используйте запрос по временным таблицам.

Как сравнить массивы структур?

Оператор = и Найти для структур по содержимому не работают. Сравнивайте по ключевому полю, формируйте строковый ключ из значимых полей или переносите данные в таблицы значений и сравнивайте запросом.

Что вернёт ВГраница() для пустого массива?

Минус один. Цикл «Для Индекс = 0 По Массив.ВГраница()» в этом случае не выполнится ни разу, поэтому два пустых массива корректно признаются равными без дополнительных проверок.

Итог

Что важно запомнить

Массивы в 1С сравнивают в коде: по длине и элементам по индексам — для полного совпадения, через Найти() — для разности и пересечения. Для больших объёмов используйте соответствие или запрос, а составные элементы сравнивайте по ключевым полям, а не оператором =.