在 C# 中删除项目时进行 HashSet 迭代

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1482234/
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-08-06 17:57:24  来源:igfitidea点击:

HashSet Iterating While Removing Items in C#

c#hashset

提问by aHunter

I have a hashset in C# that I'm removing from if a condition is met while iterating though the hashset and cannot do this using a foreach loop as below.

我在 C# 中有一个哈希集,如果在迭代哈希集时满足条件,我将删除它,并且不能使用如下的 foreach 循环来执行此操作。

foreach (String hashVal in hashset) 
{
     if (hashVal == "somestring") 
     {
            hash.Remove("somestring");
     }
}

So, how can I remove elements while iterating?

那么,如何在迭代时删除元素?

采纳答案by adrianbanks

Use the RemoveWheremethod of HashSet instead:

改用HashSet的RemoveWhere方法:

hashset.RemoveWhere(s => s == "somestring");

You specify a condition/predicate as the parameter to the method. Any item in the hashset that matches the predicate will be removed.

您指定一个条件/谓词作为方法的参数。哈希集中与谓词匹配的任何项目都将被删除。

This avoids the problem of modifying the hashset whilst it is being iterated over.

这避免了在迭代时修改哈希集的问题。



In response to your comment:

回应你的评论:

's' represents the current item being evaluated from within the hashset.

's' 表示从哈希集中评估的当前项目。

The above code is equivalent to:

上面的代码等价于:

hashset.RemoveWhere(delegate(string s) {return s == "somestring";});

or:

或者:

hashset.RemoveWhere(ShouldRemove);

public bool ShouldRemove(string s)
{
    return s == "somestring";
}


EDIT:Something has just occurred to me: since HashSet is a set that contains no duplicate values, just calling hashset.Remove("somestring")will suffice. There is no need to do it in a loop as there will never be more than a single match.

编辑:我刚刚发生了一些事情:由于 HashSet 是一个不包含重复值的集合,因此只需调用hashset.Remove("somestring")就足够了。没有必要在循环中进行,因为永远不会超过一个匹配项。

回答by Nescio

Usually when I want to iterate over something and remove values I use:

通常当我想迭代某些东西并删除我使用的值时:

 For (index = last to first)
      If(ShouldRemove(index)) Then
           Remove(index)

回答by Fredrik M?rk

You can't remove items from a collection while looping over it with an enumerator. Two approaches to solve this are:

在使用枚举器循环遍历集合时,您无法从集合中删除项目。解决这个问题的两种方法是:

  • Loop backwards over the collection using a regular indexed for-loop (which I believe is not an option in the case of a HashSet)
  • Loop over the collection, add items to be removed to another collection, then loop over the "to-be-deleted"-collection and remove the items:
  • 使用常规索引 for 循环在集合上向后循环(我认为在 a 的情况下不是一个选项HashSet
  • 循环遍历集合,将要删除的项目添加到另一个集合,然后遍历“待删除”集合并删除项目:

Example of the second approach:

第二种方法的例子:

HashSet<string> hashSet = new HashSet<string>();
hashSet.Add("one");
hashSet.Add("two");

List<string> itemsToRemove = new List<string>();
foreach (var item in hashSet)
{
    if (item == "one")
    {
        itemsToRemove.Add(item);
    }
}

foreach (var item in itemsToRemove)
{
    hashSet.Remove(item);
}

回答by javapowered

I would avoid using two foreach loop - one foreach loop is enough:

我会避免使用两个 foreach 循环——一个 foreach 循环就足够了:

HashSet<string> anotherHashSet = new HashSet<string>();
foreach (var item in hashSet)
{
    if (!shouldBeRemoved)
    {
        anotherSet.Add(item);
    }
}
hashSet = anotherHashSet;