web-dev-qa-db-ja.com

C#でアイテムを削除しながらHashSetを繰り返す

C#にハッシュセットがあり、ハッシュセットの反復中に条件が満たされた場合に削除しますが、以下のようにforeachループを使用してこれを行うことはできません。

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

では、反復中に要素を削除するにはどうすればよいですか?

24
aHunter

代わりに、HashSetの RemoveWhere メソッドを使用してください。

_hashset.RemoveWhere(s => s == "somestring");
_

メソッドのパラメーターとして条件/述語を指定します。述語に一致するハッシュセット内のアイテムはすべて削除されます。

これにより、反復処理中にハッシュセットを変更する問題が回避されます。


あなたのコメントに応えて:

「s」は、ハッシュセット内から評価されている現在のアイテムを表します。

上記のコードは次と同等です。

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

または:

_hashset.RemoveWhere(ShouldRemove);

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

EDIT:何かが起こったばかりです:HashSetは重複する値を含まないセットなので、hashset.Remove("somestring")を呼び出すだけで十分です。一致するのは1つだけなので、ループで実行する必要はありません。

49
adrianbanks

列挙子を使用してコレクションをループしている間は、コレクションからアイテムを削除することはできません。これを解決するための2つのアプローチは次のとおりです。

  • 通常のインデックス付きforループを使用してコレクションを逆方向にループします(HashSetの場合はオプションではないと思います)
  • コレクションをループし、削除するアイテムを別のコレクションに追加してから、「削除する」コレクションをループして、アイテムを削除します。

2番目のアプローチの例:

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);
}
8
Fredrik Mörk

2つのforeachループの使用は避けます。1つのforeachループで十分です。

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

通常、何かを繰り返し処理して、使用する値を削除したい場合は、次のようにします。

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