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

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

Сравнение через запрос для больших объёмов

Когда массивы содержат тысячи элементов, а сравнивать нужно по нескольким полям, удобнее переложить работу на запрос. Оба массива выгружаются в таблицы значений, помещаются во временные таблицы и соединяются полным соединением.

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Т1.Номенклатура КАК Номенклатура

|ПОМЕСТИТЬ Таб1

|ИЗ &Таб1 КАК Т1

|;

|ВЫБРАТЬ

| Т2.Номенклатура КАК Номенклатура

|ПОМЕСТИТЬ Таб2

|ИЗ &Таб2 КАК Т2

|;

|ВЫБРАТЬ

| Таб1.Номенклатура КАК ИзПервого,

| Таб2.Номенклатура КАК ИзВторого

|ИЗ Таб1 КАК Таб1

| ПОЛНОЕ СОЕДИНЕНИЕ Таб2 КАК Таб2

| ПО Таб1.Номенклатура = Таб2.Номенклатура

|ГДЕ

| Таб1.Номенклатура ЕСТЬ NULL

| ИЛИ Таб2.Номенклатура ЕСТЬ NULL";

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

Минус способа — накладные расходы на создание таблиц значений и выполнение запроса. Для массивов из десятка элементов это избыточно; порог выгоды обычно наступает на сотнях и тысячах записей.

Сравнение способов

Перебор по индексу

Подходит для проверки полной идентичности с учётом порядка; не работает для структур и не ищет различия

Соответствие со счётчиком

Сравнивает состав без учёта порядка, корректно обрабатывает дубли; требует, чтобы элементы могли быть ключами соответствия

Найти() во вложенном цикле

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

Запрос с полным соединением

Оптимален для больших массивов и сравнения по нескольким полям; требует подготовки таблиц значений

Контроль результата и типичные ошибки

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

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

Типичные ошибки
01
Сравнение массивов оператором = — сравнивается не содержимое, результат не отражает равенство элементов
02
Игнорирование дублей: проверка только вхождения без подсчёта количества даёт ложное совпадение для [1,1,2] и [1,2,2]
03
Сортировка исходного массива вместо копии — побочное изменение данных в вызывающем коде
04
Сравнение структур через = — структуры нужно сопоставлять по значениям ключей
05
Неучтённый регистр строк: "Молоко" и "молоко" — разные строки; при необходимости приводите к одному регистру через ВРег() или НРег()

Ещё одна тонкость — сравнение чисел, полученных из разных источников. Число, выгруженное из строки, может иметь другой тип или точность. При сомнениях явно приводите значения к нужному типу перед сравнением.

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

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

Пустые массивы
Норма

Функция возвращает Истина без ошибок

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

Ошибка обращения по индексу или Ложь

Массивы с дублями [1,2,2] и [2,1,2]
Норма

Совпадение при сравнении состава

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

Ложное несовпадение или ложное совпадение с [1,1,2]

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

Сразу Ложь без перебора

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

Перебор продолжается и обращается к несуществующему индексу

Исходные массивы после вызова
Норма

Порядок и содержимое не изменились

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

Массивы отсортированы или модифицированы

FAQ

Можно ли сравнить массивы в 1С одним оператором?

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

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

Оператор равенства для структур не сопоставляет их содержимое. Сравнивайте по набору ключевых полей: перебирайте пары элементов по индексу и сопоставляйте значения нужных свойств каждой структуры. Альтернатива — выгрузить данные в таблицы значений и сравнить запросом.

Как сравнить массивы без учёта регистра строк?

Приводите строковые элементы к одному регистру перед сравнением, например через ВРег() или НРег(). Делайте это при заполнении счётчика соответствия и при поиске, чтобы ключи сопоставлялись корректно.

Что быстрее: вложенный цикл с Найти() или соответствие?

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

Как проверить, что один массив полностью входит в другой?

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

Считаются ли пустые массивы равными?

Это определяет ваша функция. Логично считать два пустых массива равными: проверка количества элементов вернёт совпадение (ноль равно нулю), а цикл перебора просто не выполнится. Убедитесь, что код корректно обрабатывает этот случай и не обращается к элементу по индексу.

Итог

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

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