2009-09-26 60 views
21

我有一個C#中的哈希集,如果在迭代通過哈希集時滿足條件並且無法使用以下foreach循環執行此操作,HashSet迭代雖然刪除C#中的項目

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

那麼,如何在迭代時刪除元素?

回答

44

使用的HashSet的RemoveWhere方法代替:

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

您指定的條件/謂詞作爲參數傳遞給方法。匹配謂詞的哈希集中的任何項目都將被刪除。

這樣可以避免在迭代迭代時修改哈希集的問題。


在回答您的評論:

'S' 代表了當前項目從HashSet的範圍內被評估。

上面的代碼等同於:

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

或:

hashset.RemoveWhere(ShouldRemove); 

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

編輯: 事情剛剛發生,我:因爲HashSet的是一組不包含重複值,只需撥打hashset.Remove("somestring")即可。沒有必要在循環中進行,因爲永遠不會有多於一場比賽。

+0

謝謝你代表什麼? – aHunter 2009-09-26 21:48:21

+0

's'代表正在評估的哈希集內的當前項目。查看更新後的答案。 – adrianbanks 2009-09-26 21:53:13

1

通常當我想遍歷的東西,刪除值我用:

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

謝謝我知道我可以使用for循環,你不能使用索引位置以這種方式訪問​​HashSet。如果我使用C++,那麼我會簡單地使用指針,我不能在C#中執行此操作。 – aHunter 2009-09-26 21:44:29

+0

如果可能的話,您也可以考慮使用不同的數據結構。 – Nescio 2009-09-26 21:47:39

8

您不能使用枚舉器循環訪問集合中的項目。要解決這個有兩種方法:

  • 循環向後在使用集合定期編入索引的循環(我認爲這不是一個HashSet的情況下的一個選項)
  • 遍歷集合,添加項目被移除到另一個集合,然後在「要被刪除的」 -collection迴路和刪除的項目:

第二種方法的實施例:

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

該程序已經相當密集,所以我寧願不使用另一個列表。謝謝 – aHunter 2009-09-26 21:49:42

+0

我會避免使用兩個foreach循環 - 一個foreach循環就夠了,請參閱我的答案 – javapowered 2011-07-20 22:52:55

4

我會避免使用兩個foreach循環 - 一個foreach循環就足夠了:

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

雖然我不喜歡它的個人可以通過使用OrderedDictionary,而不是一個HashSet,並添加空作爲鍵值解決這個問題/值對。這將允許您使用for循環通過索引遍歷項目。

OrderedDictionary d = new OrderedDictionary; 
//Code to fill it up 
for (int i = 0;i < d.Count;i++) 
    if (shouldRemove(d[i])) 
     d.RemoveAt(i); 

注意,與其他數據類型有可用的OrderedDictionary沒有通用版由於這樣的事實,這將使它不可能在其中的鍵是整數的情況下,通過索引或項目訪問區分。這可能會導致很多鑄造和類型檢查,因此只有在上述解決方案不是選項時才使用它。