我正在寻找一种更好的模式,用于处理每个元素的列表,然后根据结果从列表中删除。
你不能在foreach (var element in X)中使用.Remove(element)(因为它会导致Collection被修改;枚举操作可能无法执行。例外)……你也不能使用for (int I = 0;i < elements.Count();i++)和. removeat (i),因为它破坏了你在集合中相对于i的当前位置。
有没有一种优雅的方式来做到这一点?
我正在寻找一种更好的模式,用于处理每个元素的列表,然后根据结果从列表中删除。
你不能在foreach (var element in X)中使用.Remove(element)(因为它会导致Collection被修改;枚举操作可能无法执行。例外)……你也不能使用for (int I = 0;i < elements.Count();i++)和. removeat (i),因为它破坏了你在集合中相对于i的当前位置。
有没有一种优雅的方式来做到这一点?
当前回答
List<T> TheList = new List<T>();
TheList.FindAll(element => element.Satisfies(Condition)).ForEach(element => TheList.Remove(element));
其他回答
foreach(var item in list.ToList())
{
if(item.Delete) list.Remove(item);
}
只需从第一个列表创建一个全新的列表。我说“简单”而不是“正确”,因为创建一个全新的列表可能比之前的方法具有更高的性能(我没有费心进行任何基准测试)。我通常更喜欢这种模式,它在克服Linq-To-Entities限制方面也很有用。
for(i = list.Count()-1;i>=0;i--)
{
item=list[i];
if (item.Delete) list.Remove(item);
}
这种方法使用普通的For循环向后遍历列表。如果集合的大小发生了变化,那么向前执行这个操作可能会有问题,但是向后执行应该总是安全的。
假设predicate是一个元素的布尔属性,如果它为真,则该元素应该被移除:
int i = 0;
while (i < list.Count())
{
if (list[i].predicate == true)
{
list.RemoveAt(i);
continue;
}
i++;
}
我会这样做
using System.IO;
using System;
using System.Collections.Generic;
class Author
{
public string Firstname;
public string Lastname;
public int no;
}
class Program
{
private static bool isEven(int i)
{
return ((i % 2) == 0);
}
static void Main()
{
var authorsList = new List<Author>()
{
new Author{ Firstname = "Bob", Lastname = "Smith", no = 2 },
new Author{ Firstname = "Fred", Lastname = "Jones", no = 3 },
new Author{ Firstname = "Brian", Lastname = "Brains", no = 4 },
new Author{ Firstname = "Billy", Lastname = "TheKid", no = 1 }
};
authorsList.RemoveAll(item => isEven(item.no));
foreach(var auth in authorsList)
{
Console.WriteLine(auth.Firstname + " " + auth.Lastname);
}
}
}
输出
Fred Jones
Billy TheKid
复制您正在迭代的列表。然后从副本中删除并与原件相互作用。倒退是令人困惑的,并且在并行循环时不能很好地工作。
var ids = new List<int> { 1, 2, 3, 4 };
var iterableIds = ids.ToList();
Parallel.ForEach(iterableIds, id =>
{
ids.Remove(id);
});
使用.ToList()将创建一个列表的副本,正如这个问题中所解释的: ToList()—它是否创建一个新列表?
通过使用ToList(),可以从原始列表中删除,因为实际上是在迭代一个副本。
foreach (var item in listTracked.ToList()) {
if (DetermineIfRequiresRemoval(item)) {
listTracked.Remove(item)
}
}