Правильное удаление строк
Как обычно очень простая задача. Зачем такое вообще пишу, ведь легко и быстро гуглится, да и языковые модели все это знают и умеют. Но ключевое слово здесь "Правильное"...
Итак имеем таблицу, например табличную часть документа, где главная колонка - номенклатура. Например:
1. Помидор 2. Огурец 3. Редиска 4. Лук 5. Укроп
Допустим хотим удалить Помидор и Редиску. И для этого у нас заполнился МассивИндексовДляУдаления с соответствующими индексами 0 и 2...
Возьмем цикл с прямым обходом:
Для Каждого Индекс из МассивИндексовДляУдаления Цикл Таблица.Удалить(Индекс); КонецЦикла;
При этом удалятся Помидор и Лук. Потому что после удаления строки помидора, строка лука станет третьей (с индексом 2). Эта ошибка известна всем.
Хорошо, тогда давайте сделаем цикл с обратным обходом, ну или проще, отсортируем наш массив индексов по убыванию:
Список = Новый СписокЗначений; Список.ЗагрузитьЗначения(МассивИндексовДляУдаления); Список.СортироватьПоЗначению(НаправлениеСортировки.Убыв); МассивИндексовДляУдаления = Список.ВыгрузитьЗначения(); Для Каждого Индекс из МассивИндексовДляУдаления Цикл Таблица.Удалить(Индекс); КонецЦикла;
Удалились Помидор и Редиска. Все работает, все отлично. Но давайте порассуждаем дальше. Зачем нам удалять строки? Вероятно срабатывает какая-то проверка, которая по какому-то условию находит лишнее и заполняет массив для удаления. А если мы потом добавили еще одну проверку. И какая-то строка была настолько отвратительной, что не прошла обе проверки и в итоге в массив для удаления ее индекс добавится дважды. Ведь мы же обязательно забудем проконтролировать дубли :-) Как сработает наш код, если попробовать дважды удалить Редиску? А удалятся Редиска и Лук. Без какой-либо сигнализации об ошибке. И всплывет это счастье вовсе не на тестах, а уже в эксплуатации когда успеет много чего испортить.
Поэтому всегда следует удалять строки не по индексу, а по значению. То есть в массив для удаления нужно добавлять сами строки таблицы:
Для Каждого СтрокаТаблицы из МассивСтрокДляУдаления Цикл Таблица.Удалить(СтрокаТаблицы); КонецЦикла;
Это же даже проще. Синтаксис такой-же, а направление обхода теперь не важно. Ну а если в массиве появится задвоение, удалить уже удаленную строку не удастся, поэтому будет вызвано исключение, пользователю выведется информация об ошибке, при этом ничего не испортится. Программист добавит проверку массива на дубли и все будет хорошо.
Ну то есть, этот конкретный пример подталкивает нас к использованию двух фундаментальных принципов:
Не нужно делать сложно, если можно сделать просто
Не нужно использовать потенциально опасные приемы, даже если это разрешено
←39 | заметка 40