Это будет сделано:
IEnumerable<T> FilterAndRemove(this List<T> list, Func<T, bool> pred)
{
List<T> filtered = new List<T>();
int i = 0;
while(i < list.Count)
{
if (pred(list[i]))
{
filtered.Add(list[i]);
list.RemoveAt(i);
}
else
{
++i;
}
}
return list;
}
Но я уверен, что вы уже подумали о чем-то подобном. Можете ли вы обновить свой ответ с той эффективностью, которую вы ищете?
Обратите внимание, что две фильтрации с pred
и !pred
в исходном списке все равно будут иметь значение O (n) и вовсе не будут неэффективными. Особенно если учесть, что вы получите полное преимущество от ленивой оценки для обоих наборов результатов. См. Также ответ Роба.
Этот алгоритм находится в O (n ^ 2).
Вместо удаления каждого элемента вы также можете собрать их в новый список и скопировать их в список ввода перед возвратом. Это также даст вам O (n).
Еще одна опция для O (n) будет переключаться на связанный список.