Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HashSet Iterating While Removing Items in C#

Tags:

c#

hashset

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?

like image 831
aHunter Avatar asked Sep 26 '09 21:09

aHunter


People also ask

Can you remove from a set while iterating?

Since we can't modify a set while iterating over it, we can create a duplicate set and remove elements that satisfy the condition from the original set by iterating over the duplicate set.

How to remove item from HashSet c#?

Remove(T) method is used to removes the specified element from a HashSet<T> object. Syntax: public bool Remove (T item); Here, item is the element which is to be remove.

Can you iterate through a HashSet C#?

The standard solution to iterate over the HashSet<T> object is using a foreach loop. The following example shows the usage of the foreach for printing the contents of a set. Note that a HashSet<T> does not provide an indexer.


3 Answers

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.

like image 87
adrianbanks Avatar answered Sep 29 '22 07:09

adrianbanks


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);
}
like image 29
Fredrik Mörk Avatar answered Sep 29 '22 09:09

Fredrik Mörk


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;
like image 44
Oleg Vazhnev Avatar answered Sep 29 '22 09:09

Oleg Vazhnev