Страницы

Поиск по вопросам

воскресенье, 2 февраля 2020 г.

Прогон в foreach с изменением количества элементов

#c_sharp #многопоточность #циклы #foreach #parallel


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

Вначале думал про for и если удаляем, делать i--, т.к. уменьшилось количество элементов
на 1, но это не сделать при параллельном прогоне, поэтому думаю сделать подобное в
foreach, чтобы не привязываться к индексу элемента. Но при изменение foreach выскакивает
исключение, что логично.

Можно ли как-нибудь прогнать параллельно по циклу и по условию, если что удалить
элемент. Чтобы это не сказывалась на других элементах в параллельных потоках?
    


Ответы

Ответ 1



Если удалять элемент из коллекции сразу же на месте не требуется — заведите еще одну (потокобезопасную) коллекцию, элементы подлежащие удалению складывайте в нее, после завершения первого цикла просто удалите из первой коллекции все элементы, присутствующие во второй: // заводим коллекцию var forRemoving = new ConcurrentBag(); foreach (var item in items) { ... // складываем в нее элементы подлежащие удалению forRemoving.Add(item); } // удаляем foreach (var item in forRemoving) items.Remove(item); Если для вашей задачи не принципиально удаление элементов из входной коллекции, а подойдет также вариант с формированием новой коллекцией — можно воспользоваться функционалом Parallel Linq: var result = items.AsParallel() .Where(item => condition(item)) .ToList();

Ответ 2



У меня есть список. Если список - это именно List, то используй обычный цикл for. Обращаю внимание, что удаление нескольких элементов через Remove неэффективно, поскольку приведёт к квадратичной асимптотике (хвост всё время сдвигается). Правильным вариантом было бы использовать метод RemoveAll. Ну либо написать обраотку списка в один проход с ручным сдвигом конца по мере порверки.

Комментариев нет:

Отправить комментарий