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

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

Как удалить строки из массива в 1С

Как удалить строки из массива в 1С: метод Удалить(), удаление по условию в цикле, типичные ошибки со сдвигом индексов и готовые примеры кода на встроенном языке.

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

Главная ловушка — сдвиг индексов. Когда вы удаляете элемент из середины массива, все последующие элементы смещаются на одну позицию влево. Если удалять в прямом цикле Для Сч = 0 По ..., часть элементов будет пропущена. Поэтому безопасные шаблоны удаления — обратный цикл, цикл Пока с ручным управлением индексом или сборка нового массива без лишних элементов.

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

Метод Удалить(): синтаксис и поведение

Метод Удалить() принимает один параметр — индекс удаляемого элемента. Индексация массива начинается с нуля, поэтому первый элемент имеет индекс 0, а последний — Массив.Количество() - 1. После удаления количество элементов уменьшается на единицу, а все элементы правее удалённого сдвигаются на одну позицию.

Пример простого удаления по известному индексу:

МассивТоваров = Новый Массив;

МассивТоваров.Добавить("Клавиатура");

МассивТоваров.Добавить("Мышь");

МассивТоваров.Добавить("Монитор");

МассивТоваров.Удалить(1); // удалён элемент "Мышь"

// Теперь МассивТоваров[1] содержит "Монитор"

Если передать индекс за границами массива (отрицательный или больше либо равный количеству элементов), платформа выдаст ошибку «Индекс находится за границами массива». Поэтому перед удалением по вычисленному индексу полезно проверять его диапазон.

Удаление элемента по значению

Метода «удалить по значению» в массиве 1С нет, поэтому сначала нужно найти индекс элемента через Найти(), а затем удалить его. Метод Найти() возвращает индекс первого вхождения или Неопределено, если значение не найдено — это нужно обязательно проверять.

Индекс = МассивТоваров.Найти("Мышь");

Если Индекс <> Неопределено Тогда

МассивТоваров.Удалить(Индекс);

КонецЕсли;

Учтите два момента. Во-первых, Найти() ищет точное совпадение с учётом типа: строка "5" и число 5 — разные значения. Во-вторых, если в массиве несколько одинаковых значений, будет удалено только первое. Для удаления всех вхождений нужен цикл:

Пока Истина Цикл

Индекс = МассивТоваров.Найти("Мышь");

Если Индекс = Неопределено Тогда

Прервать;

КонецЕсли;

МассивТоваров.Удалить(Индекс);

КонецЦикла;

Удаление строк по условию: обратный цикл

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

Для Сч = 1 По МассивДанных.Количество() Цикл

Индекс = МассивДанных.Количество() - Сч;

Если НЕ ЗначениеЗаполнено(МассивДанных[Индекс]) Тогда

МассивДанных.Удалить(Индекс);

КонецЕсли;

КонецЦикла;

Этот шаблон подходит для любых условий: пустые строки, нулевые суммы, отменённые документы, дубли. Условие может быть сколь угодно сложным — например, проверка свойств объекта, хранящегося в элементе массива.

Альтернатива: цикл Пока с ручным управлением индексом

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

Индекс = 0;

Пока Индекс < МассивДанных.Количество() Цикл

Если МассивДанных[Индекс].Сумма = 0 Тогда

МассивДанных.Удалить(Индекс);

Иначе

Индекс = Индекс + 1;

КонецЕсли;

КонецЦикла;

Логика проста: после удаления на текущей позиции оказывается новый, ещё не проверенный элемент, поэтому индекс увеличивать нельзя. Если элемент оставлен — переходим к следующему. Условие цикла пересчитывает Количество() на каждой итерации, поэтому выхода за границы не происходит.

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

Очистка массива и альтернатива через новый массив

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

МассивДанных.Очистить(); // элементов больше нет, объект тот же

Иногда вместо удаления проще собрать новый массив из нужных элементов. Этот подход особенно удобен, когда условие «оставить» формулируется проще, чем условие «удалить», или когда массив большой и удалений много — каждый вызов Удалить() сдвигает хвост массива, а однократный проход с добавлением работает предсказуемо:

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

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

Если ЗначениеЗаполнено(Элемент) Тогда

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

КонецЕсли;

КонецЦикла;

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

Обратный цикл с Удалить()

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

Цикл Пока с ручным индексом

Гибкий вариант, когда важен прямой порядок обхода. Чуть больше кода и выше риск забыть увеличить индекс.

Сборка нового массива

Проще и безопаснее при большом числе удалений, но создаёт новый объект — ссылки на старый массив не обновятся.

Метод Очистить()

Единственный правильный способ удалить все элементы, сохранив объект массива.

Частый случай: удаление строк из таблицы значений и табличной части

На практике под «массивом» нередко имеют в виду таблицу значений или табличную часть документа. Там логика та же — есть метод Удалить(), но он принимает не индекс, а саму строку. Обратный цикл работает и здесь:

ВсегоСтрок = ТаблицаДанных.Количество();

Для Сч = 1 По ВсегоСтрок Цикл

СтрокаТаблицы = ТаблицаДанных[ВсегоСтрок - Сч];

Если СтрокаТаблицы.Количество = 0 Тогда

ТаблицаДанных.Удалить(СтрокаТаблицы);

КонецЕсли;

КонецЦикла;

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

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

Типичные ошибки
01
Удаление в прямом цикле Для — часть элементов пропускается из-за сдвига индексов
02
Удаление по результату Найти() без проверки на Неопределено — ошибка «Индекс за границами массива»
03
Использование индекса, вычисленного до удаления других элементов — удаляется не тот элемент
04
Ожидание, что Удалить() в табличной части сразу меняет базу — без Записать() изменения теряются
05
Забытое увеличение индекса в цикле Пока — бесконечный цикл

После реализации удаления проверьте код на граничных сценариях. Пустой массив не должен вызывать ошибку. Если под условие попадают все элементы, в результате массив должен стать пустым, а не содержать «хвост». Если ни один элемент не подходит — массив должен остаться неизменным. Эти три теста быстро выявляют ошибки в управлении индексами.

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

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

Количество элементов после удаления
Норма

Равно исходному минус число удалённых

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

Удалились лишние или остались элементы под условием

Пустой исходный массив
Норма

Код отрабатывает без ошибок

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

Ошибка «Индекс за границами массива»

Все элементы под условием
Норма

Массив пуст или Очистить() вызван корректно

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

Остались элементы — признак пропусков в прямом цикле

Табличная часть документа
Норма

После Записать() строки отсутствуют в базе

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

В форме строк нет, а в базе остались — объект не записан

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

Итог

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

Удаление выполняется методом Удалить(Индекс), поиск позиции — через Найти() с проверкой на Неопределено. Удаляйте по условию в обратном цикле или в цикле Пока без увеличения индекса при удалении. Для полной очистки используйте Очистить(). В табличных частях изменения сохраняются только после записи объекта.

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

Можно ли удалить элемент массива по значению одной командой?

Нет, отдельного метода «удалить по значению» у массива нет. Сначала найдите индекс через Найти(), проверьте, что он не равен Неопределено, и затем вызовите Удалить(Индекс). Для удаления всех вхождений оберните этот код в цикл Пока.

Почему при удалении в цикле «Для каждого» возникает ошибка?

Цикл «Для каждого» перебирает коллекцию по внутреннему итератору, и изменение состава коллекции во время обхода нарушает его работу — платформа выдаёт ошибку или поведение становится непредсказуемым. Удаляйте элементы в обратном цикле по индексам или в цикле Пока.

Чем Очистить() отличается от присваивания нового пустого массива?

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

Как удалить дубли из массива?

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

Удаляются ли строки табличной части из базы сразу после Удалить()?

Нет. Метод Удалить() меняет только данные объекта в памяти. Чтобы изменения зафиксировались в информационной базе, объект нужно записать методом Записать(). Если работа идёт в форме, запись обычно выполняется при нажатии «Записать» или «Провести».

Что быстрее: удаление лишних элементов или сборка нового массива?

Зависит от доли удаляемых элементов. Если удаляется несколько позиций из большого массива — дешевле Удалить(). Если отбрасывается значительная часть элементов, однократный проход со сборкой нового массива обычно эффективнее, потому что каждое Удалить() сдвигает весь хвост массива. Для типовых объёмов данных в учётных задачах разница редко критична — выбирайте более читаемый вариант.