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

Разработка и Конфигурация · 12 мин

Как сравнить два массива в 1С: практические способы и примеры

Способы сравнения двух массивов в 1С: циклы, соответствия, ЗначениеВСтрокуВнутр, поиск различий и пересечений. Примеры кода, ошибки и советы по производительности.

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

Ключевой момент перед выбором метода — определить семантику сравнения. Массивы [1, 2, 3] и [3, 2, 1] содержат одинаковые элементы, но в разном порядке. Если порядок важен (например, строки табличной части), нужно сравнивать поэлементно по индексам. Если важен только состав — достаточно сравнения множеств. От этого решения зависит вся логика дальнейшего кода.

Вторая развилка — тип элементов. Примитивные значения (числа, строки, даты, ссылки) сравниваются оператором «=». А вот структуры, таблицы значений и другие составные объекты оператором «=» корректно не сравниваются — потребуется сериализация через ЗначениеВСтрокуВнутр или поэлементный обход полей.

Определяем, что считать равенством массивов

Прежде чем писать код, зафиксируйте три вопроса. Первый: важен ли порядок элементов? Второй: учитываются ли дубликаты — массивы [1, 1, 2] и [1, 2] равны как множества, но не равны как списки. Третий: что делать с типами — строка «5» и число 5 в 1С не равны, и строгое сравнение это выявит.

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

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

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

Функция МассивыРавны(Массив1, Массив2)

Если Массив1.Количество() <> Массив2.Количество() Тогда

Возврат Ложь;

КонецЕсли;

Для Индекс = 0 По Массив1.Количество() - 1 Цикл

Если Массив1[Индекс] <> Массив2[Индекс] Тогда

Возврат Ложь;

КонецЕсли;

КонецЦикла;

Возврат Истина;

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

Такой подход работает за один проход и легко отлаживается. Его ограничение — чувствительность к порядку: перестановка элементов даст результат «не равны». Если порядок не важен, перед сравнением отсортируйте оба массива (например, выгрузив в список значений и вызвав СортироватьПоЗначению()) либо используйте метод с соответствиями из следующего раздела.

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

Способ 2. Быстрая проверка через ЗначениеВСтрокуВнутр

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

МассивыРавны = (ЗначениеВСтрокуВнутр(Массив1) = ЗначениеВСтрокуВнутр(Массив2));

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

Способ 3. Поиск различий через соответствия

Когда нужно не просто «равны/не равны», а конкретный список расхождений, оптимален подход с соответствиями. Идея: элементы первого массива помещаются в соответствие как ключи, затем по нему проверяется каждый элемент второго массива. Поиск в соответствии работает в среднем за константное время, поэтому общая сложность линейна.

// Элементы, которые есть в Массив1, но отсутствуют в Массив2

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

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

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

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

КонецЦикла;

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

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

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

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

КонецЕсли;

КонецЦикла;

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

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

Вызвав функцию дважды — РазностьМассивов(М1, М2) и РазностьМассивов(М2, М1) — вы получите обе стороны расхождения: что удалено и что добавлено. Это стандартный приём при сравнении табличных частей до и после редактирования, при сверке выгрузок и при синхронизации данных между системами.

Пересечение (общие элементы) строится зеркально: в результат попадают элементы, для которых Индекс[Элемент] <> Неопределено. Если дубликаты важны, в значение соответствия вместо Истина записывают счётчик вхождений и уменьшают его при обходе второго массива.

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

Сравнение массивов структур и составных объектов

Частая ситуация — массив содержит структуры, например строки данных, полученные из JSON или из запроса. Оператор «=» для структур сравнивает не содержимое, а фактически неприменим в ожидаемом смысле, поэтому прямое сравнение Структура1 = Структура2 не даст корректного результата по значениям полей.

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

Если массивы формируются из запроса, рассмотрите альтернативу: выгрузить результат в таблицу значений и использовать её индексы или свёртку. Во многих задачах сверки таблица значений удобнее массива структур, потому что платформа предоставляет для неё встроенные механизмы поиска и группировки.

Производительность: что выбрать для больших массивов

Наивное решение «для каждого элемента первого массива искать его во втором через Найти()» имеет квадратичную сложность: на массивах по 10 000 элементов это порядка ста миллионов операций сравнения. На тонком клиенте такой цикл может занимать заметное время и блокировать интерфейс пользователя.

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

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

Цикл по индексам

Подходит, когда важен порядок и нужна позиция расхождения. Линейная сложность, но только для массивов одинаковой структуры.

ЗначениеВСтрокуВнутр

Самый короткий код для проверки «равны/не равны». Не показывает различия, зависит от порядка и формата платформы.

Соответствия (хеш-индекс)

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

Вложенный цикл с Найти()

Прост в написании, но квадратичная сложность. Приемлем только для массивов до сотни элементов.

Порядок выбора метода
  1. 1
    Определите, важен ли порядок элементов и дубликаты
  2. 2
    Проверьте тип элементов: примитивы, ссылки или структуры
  3. 3
    Оцените размер массивов: до сотни элементов — любой метод, больше — соответствия
  4. 4
    Выберите код из соответствующего раздела и оформите как функцию общего модуля
  5. 5
    Протестируйте на граничных случаях: пустые массивы, один элемент, все элементы разные

Частые ошибки и проверка результата

Самая распространённая ошибка — сравнение массивов разной длины в цикле по длине одного из них: при обращении к несуществующему индексу возникает ошибка «Индекс находится за границами массива». Всегда проверяйте Количество() до входа в цикл.

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

Отдельного внимания заслуживает значение Неопределено: если оно встречается в массивах, помните, что проверка Индекс[Элемент] = Неопределено в методе с соответствиями не отличит «элемента нет» от «элемент есть и равен Неопределено». В таких случаях используйте в соответствии маркер-значение, отличное от Неопределено, и проверяйте наличие ключа через него.

Типичные ошибки
01
Сравнение без проверки Количество() — обращение за границу массива и падение кода
02
Вложенный цикл с Найти() на больших массивах — квадратичная сложность и зависание обработки
03
Сравнение значений разных типов (строка vs число) — ложные расхождения при внешне одинаковых данных
04
Ожидание, что структуры сравнятся оператором = по содержимому — нужен ключ или сериализация
05
Игнорирование порядка элементов там, где он важен, или его учёт там, где важен только состав
Контрольные точки

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

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

Два пустых массива считаются равными, разность пуста

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

Ошибка обращения к индексу или результат «не равны»

Перестановка элементов
Норма

Результат соответствует выбранной семантике (учитывать порядок или нет)

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

Метод сортировки не применён, а порядок не важен — ложное «не равны»

Большие массивы
Норма

Сравнение 10 000+ элементов выполняется быстро, без заметной паузы

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

Используется вложенный цикл с Найти() — обработка тормозит

Частые вопросы

Можно ли сравнить два массива одной встроенной функцией?

Готовой функции «МассивыРавны» в платформе нет. Ближайший однострочный вариант — сравнение результатов ЗначениеВСтрокуВнутр для обоих массивов. Для остальных задач (различия, пересечения) пишется собственная функция, обычно её размещают в общем модуле для повторного использования.

Как сравнить массивы без учёта порядка элементов?

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

Работает ли сравнение, если в массиве ссылки на объекты базы?

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

Что делать, если массивы содержат структуры?

Сравнивайте по ключевому полю (код, идентификатор, ссылка внутри структуры) — это быстрее всего. Если ключевого поля нет, сериализуйте каждую структуру через ЗначениеВСтрокуВнутр и сравнивайте полученные строки, либо напишите функцию пополевого сравнения.

Где выполнять сравнение больших массивов — на клиенте или сервере?

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

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

Сохраните массив ссылок (или ключей строк) до редактирования, после редактирования сформируйте второй массив и примените функцию разности дважды: Разность(Было, Стало) даст удалённые элементы, Разность(Стало, Было) — добавленные.

Итог

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

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