Question

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.

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

So, how can I remove elements while iterating?

Was it helpful?

Solution

Use the RemoveWhere method of HashSet instead:

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.

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.

OTHER TIPS

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:

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);
}

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

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

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

 For (index = last to first)
      If(ShouldRemove(index)) Then
           Remove(index)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top