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