目前,我能想到的最好的是:
bool oneMoreTime = true;
while (oneMoreTime)
{
ItemType toDelete=null;
oneMoreTime=false;
foreach (ItemType item in collection)
{
if (ShouldBeDeleted(item))
{
toDelete=item;
break;
}
}
if (toDelete!=null)
{
collection.Remove(toDelete);
oneMoreTime=true;
}
}
我知道我在这里至少有一个额外的变量,但我把它包括在内以提高算法的可读性。
答案 0 :(得分:34)
“RemoveAll”方法最好。
另一种常见技术是:
var itemsToBeDeleted = collection.Where(i=>ShouldBeDeleted(i)).ToList();
foreach(var itemToBeDeleted in itemsToBeDeleted)
collection.Remove(itemToBeDeleted);
另一种常见的技巧是使用“for”循环,但要确保你向后:
for (int i = collection.Count - 1; i >= 0; --i)
if (ShouldBeDeleted(collection[i]))
collection.RemoveAt(i);
另一种常见技巧是将不的项目添加到新集合中:
var newCollection = new List<whatever>();
foreach(var item in collection.Where(i=>!ShouldBeDeleted(i))
newCollection.Add(item);
现在你有两个系列。如果你想最终得到两个集合,我特别喜欢的一种技术是使用不可变数据结构。使用不可变数据结构,“删除”项不会改变数据结构;它会返回一个新的数据结构(如果可能的话,重新使用旧的数据结构),它没有你删除的项目。使用不可变数据结构,你不会修改你正在迭代的东西,所以没有问题:
var newCollection = oldCollection;
foreach(var item in oldCollection.Where(i=>ShouldBeDeleted(i))
newCollection = newCollection.Remove(item);
或
var newCollection = ImmutableCollection<whatever>.Empty;
foreach(var item in oldCollection.Where(i=>!ShouldBeDeleted(i))
newCollection = newCollection.Add(item);
当你完成后,你有两个收藏。新的项目已删除,旧项目与以前相同。
答案 1 :(得分:14)
正当我完成输入时,我记得有一种lambda方式可以做到。
collection.RemoveAll(i=>ShouldBeDeleted(i));
更好的方式?
答案 2 :(得分:2)
向后for
循环的正向变体:
for (int i = 0; i < collection.Count; )
if (ShouldBeDeleted(collection[i]))
collection.RemoveAt(i)
else
i++;
答案 3 :(得分:1)
lambda方式很好。你也可以使用常规for循环,你可以迭代for循环在循环中使用的列表,不像foreach循环。
for (int i = collection.Count-1; i >= 0; i--)
{
if(ShouldBeDeleted(collection[i])
collection.RemoveAt(i);
}
我假设这里的集合是一个arraylist,如果你使用不同的数据结构,代码可能会有所不同。
答案 4 :(得分:1)
您无法从foreach
循环内的集合中删除(除非它是一个非常特殊的集合,具有特殊的枚举器)。如果在枚举集合时修改了集合,BCL集合将抛出异常。
您可以使用for
循环删除单个元素并相应地调整索引。但是,这样做可能容易出错。根据底层集合的实现,删除单个元素可能也很昂贵。例如,删除List<T>
的第一个元素将复制列表中的所有重新元素。
最好的解决方案通常是根据旧版本创建一个新的集合:
var newCollection = collection.Where(item => !ShouldBeDeleted(item)).ToList();
使用ToList()
或ToArray()
创建新集合,或从IEnumerable
子句返回的Where()
初始化您的特定集合类型。