.net 如何从循环中的 Enumerable 集合中删除对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/404557/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 10:55:07  来源:igfitidea点击:

How to remove objects from an Enumerable collection in a loop

.netdesign-patternsienumerable

提问by johnc

Duplicate

复制

Modifying A Collection While Iterating Through It

在迭代时修改集合



Has anyone a nice pattern to allow me to get around the inability to remove objects while I loop through an enumerable collection (eg, an IList or KeyValuePairs in a dictionary)

有没有人有一个很好的模式可以让我在遍历可枚举集合(例如,字典中的 IList 或 KeyValuePairs)时解决无法删除对象的问题

For example, the following fails, as it modifies the List being enumerated over during the foreach

例如,以下失败,因为它修改了在 foreach 期间枚举的 List

foreach (MyObject myObject in MyListOfMyObjects)
{
     if (condition) MyListOfMyObjects.Remove(myObject);
}

In the past I have used two methods.

过去我使用了两种方法。

I have replaced the foreach with a reversed for loop (so as not to change the any indexes I am looping over if I remove an object).

我已经用反向 for 循环替换了 foreach(以免在删除对象时更改我正在循环的任何索引)。

I have also tried storing a new collection of objects to remove within to loop, then looping through that collection and removed the objects from the original collection.

我还尝试存储要在循环中删除的新对象集合,然后循环遍历该集合并从原始集合中删除对象。

These work fine, but neither feelsnice, and I was wondering if anyone has come up with a more elegantsolution to the issue

这些工作正常,但都感觉不好,我想知道是否有人提出了更优雅的解决方案

采纳答案by ChrisW

There's a useful List<T>.RemoveAll(Predicate<T> match)method which I think is designed for this: http://msdn.microsoft.com/en-us/library/wdka673a.aspx

List<T>.RemoveAll(Predicate<T> match)我认为有一个有用的方法是为此设计的:http: //msdn.microsoft.com/en-us/library/wdka673a.aspx

回答by Mark Maxham

It's kind of simple-minded, but when I plan to delete items from an IEnumerable/IList I usually just make a copy:

这有点简单,但是当我计划从 IEnumerable/IList 中删除项目时,我通常只制作一个副本:

foreach (MyObject myObject in new List<MyObject>(MyListOfMyObjects))
{
     if (condition) MyListOfMyObjects.Remove(myObject);
}

It's not the most efficient way to do it, but it's easy to read. Premature optimization and all that.

这不是最有效的方法,但它很容易阅读。过早的优化等等。

回答by TheSoftwareJedi

Do the inverse, creating a new list:

做相反的事情,创建一个新列表:

List myFilteredList = new List();
foreach (MyObject myObject in myListOfMyObjects)
{
     if (!condition) myFilteredList.Add(myObject);
}

Then use the new list wherever you need it.

然后在任何需要的地方使用新列表。

You can also use a LINQ expression easily, again, inversing the condition. This has the added benefit of not creating a new structure, but also the pitfalls of it being a lazy enumerable:

您还可以轻松地使用 LINQ 表达式,再次反转条件。这具有不创建新结构的额外好处,但也有它是一个惰性可枚举的陷阱:

var myFilteredList = from myObject in myListOfMyObjects
                     where !condition
                     select myObject;

However, if you truly need to remove the items from the list, I typically use the "create a new list, then reiterate and remove" approach.

但是,如果您确实需要从列表中删除项目,我通常使用“创建一个新列表,然后重复并删除”的方法。

回答by calvin

I just came across this post and thought I would share.

我刚看到这篇文章,想分享一下。

void RemoveAll(object condition)  
{

    bool found = false;

    foreach(object thisObject in objects)    
    {

        if (condition)    
        {    
            objects.Remove(thisObject);

            found = true;

            break; //exit loop    
        }     
     }

    // Call again recursively

    if (found) RemoveAll(condition);

}

回答by Richard Watson

I have a dictionary and want to Dispose of all Values. When each value is disposed it removes itself from the dictionary which creates the problem you discuss. I did the following:

我有一本字典,想处理所有值。当每个值被处理时,它会从字典中删除自己,这会产生你讨论的问题。我做了以下事情:

foreach (var o in dictionary.Values.ToList())
{
  o.Dispose();
}

回答by Rob Walker

I don't like the reversed for loop idea, since that only works on certain data structures.

我不喜欢反向循环的想法,因为它只适用于某些数据结构。

In general I'd use the second technique and accumulate the items to be deleted in a separate 'to-be-deleted' collection. If deletion can cause existing iterates to be invalidated (as will happen with any balanced tree collection for example) then I don't see a way around this.

一般来说,我会使用第二种技术并将要删除的项目累积在一个单独的“待删除”集合中。如果删除会导致现有迭代无效(例如,任何平衡树集合都会发生这种情况),那么我看不到解决方法。

The only other technique that I've occasionally used is to restart the whole iteration when you find the first element to delete. If you make it through without finding any items to delete then the function is finished. This is inefficient, but sometimes neccessary if deleting one item from the collection may change the set of items that need to be deleted.

我偶尔使用的唯一其他技术是在找到要删除的第一个元素时重新启动整个迭代。如果您通过而没有找到任何要删除的项目,则该功能已完成。这是低效的,但有时如果从集合中删除一个项目可能会更改需要删除的项目集,则有时是必要的。

回答by DC.

I appreciate this may be dead now but the way I always do this is:

我很欣赏这现在可能已经死了,但我总是这样做的方式是:

foreach (MyObject myObject in MyListOfMyObjects)
{

foreach (MyListOfMyObjects 中的 MyObject myObject)
{

if (condition) MyListOfMyObjects.Remove(myObject);

如果(条件)MyListOfMyObjects.Remove(myObject);

break;

休息;

}

}

Object is removed and then loop exits, viola!

对象被移除,然后循环退出,中提琴!