Реклама на этом месте
Форум 1С
Форум 1С
Программистам. Бухгалтерам. Администраторам. Пользователям
Задай вопрос - получи решение проблемы. Без троллинга и флуда.
17 Дек 2017, 18:52
МультиВход
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Не получили письмо с кодом активации?
 
collapse

Автор Тема: Как удалить элементы коллекции?  (Прочитано 5968 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн MuI_I_Ika

  • Гончаров Михаил
  • Администратор
  • *****
  • Сообщений: 6558
  • РЕПУТАЦИЯ: 775
  • КПД: 12%
  • Регистрация: 2012-08-15
    • Skype: MuI_I_Ika
  • Сайт: 
  • Профессия: Программист 1С

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


Первое что приходит обычно в голову - это перебрать коллекцию циклом, и при соблюдении условия удалить элемент методом


Удалить();
Однако, такой подход зачастую сопряжен с определенными трудностями. Ну например, для обхода коллекции вы решили использовать цикл:
Для Каждого Элемент из ТаблицаЗначений Цикл


КонецЦикла;
Что произойдет в том случае если вы в середине выполнения цикла удалите какой-либо элемент из этой же коллекции? Программа просто пропустит элемент, следующий за удаленным. Это произойдет из-за того, что обход осуществляется по индексу элементов. После удаления индекс следующего элемента уменьшится. А программа будет обращаться к индексу следующему за удаленным (тому который был до момента удаления).


Если представить схематически то получаются две картины до удаления и после удаления:


1          1
2          2 (был 3)
3          3 (был 4)
4


Произошло удаление 2-го элемента. Элементы 3 и 4 сместились в позиции 2 и 3. А программа уже обработала 2-ой элемент и будет обращаться к 3-му.


Если же удалить 3-ий элемент, то программа попытается обратиться к 4-му и возникнет ошибка.


Такая же проблема нас ожидает при использовании цикла


Для к = 0 по ТаблицаЗначений.Количество()-1 Цикл


КонецЦикла;
Дело в том, что для оптимизации производительности количество элементов коллекции вычисляется один раз в начале выполнения цикла, и в дальнейшем уже не пересчитывается. Соответственно и получаем проблему такую же как и в первом случае.


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


Вот как будет выглядеть код:


     НайденныеСсылки = НайтиПоСсылкам(МассивСсылок);

//почистим от метаданных исключений
МассивНаУдаление = Новый Массив;


Для каждого Элемент из НайденныеСсылки Цикл

Для каждого ЭлементИсключение из ОбъектыИсключения Цикл
Если Элемент.Метаданные = Метаданные.НайтиПоПолномуИмени(ЭлементИсключение.ТипОбъекта) Тогда
МассивНаУдаление.Добавить(Элемент);
КонецЕсли;
КонецЦикла;

КонецЦикла;

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

НайденныеСсылки.Удалить(Элемент);

КонецЦикла;


Второй вариант удаления строк по условию - это перебор коллекции (в данном случае таблицы значений) с конца. То есть сначала вы обрабатываете самый последний элемент, а конце самый первый. Таким образом программа не собъется со счету, если вы удалите один из элементов посередине, поскольку она будет переходить к элементам с меньшим индексом.


Пример кода:


	Для Индекс = -ТаблицаЗначений.Количество()+1 По 0 Цикл

Если ТаблицаЗначений[-Индекс].Количество = 0 Тогда
ТаблицаЗначений.Удалить(-Индекс);
КонецЕсли;

КонецЦикла;


Отмечу, что 1С не поддерживает в цикле Для По переход от большего элемента к меньшему, поэтому здесь применена небольшая хитрость - использование отрицательных чисел.


Третий вариант - использование цикла Пока. Пример кода:


Индекс = ТаблицаКонтрагентов.Количество() - 1; 
Пока Индекс >= 0 Цикл
Если ТаблицаКонтрагентов[Индекс].СуммаЗадолженности = 0 Тогда
ТаблицаКонтрагентов.Удалить(Индекс);
КонецЕсли;

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


КонецЦикла;


 


* Живое общение

Не устроил ответ?

Зарегистрируйся и задай свой вопрос. Живое общение приносит результат намного быстрее.


Зарегистрироваться

* Реклама

* Поиск

* Последние задачи на разработку (фриланс)

* Реклама

* Последние вакансии

* Топ 10 авторов за месяц

Геннадий ОбьГЭС Геннадий ОбьГЭС
145 Сообщений
ilyay ilyay
63 Сообщений
AIFrame
63 Сообщений
alex0402
50 Сообщений
andron81_81
44 Сообщений
oleg-x
42 Сообщений
BuhRust
32 Сообщений
MuI_I_Ika MuI_I_Ika
31 Сообщений
Golickoff Golickoff
28 Сообщений
alexandr_ll
24 Сообщений

* Кто онлайн

  • Точка Гостей: 285
  • Точка Скрытых: 0
  • Точка Пользователей: 7
  • Точка Сейчас на форуме:

* Облако тэгов

* Форум 1С с мобильного

* Инструменты

* Дополнительно

Поиск

 
SimplePortal 2.3.5 © 2008-2012, SimplePortal