Итерация HashSet при удалении элементов в C#
Вопрос
У меня есть хэш-набор на C#, который я удаляю, если при повторении хэш-набора выполняется условие, и я не могу сделать это с помощью цикла foreach, как показано ниже.
foreach (String hashVal in hashset)
{
if (hashVal == "somestring")
{
hash.Remove("somestring");
}
}
Итак, как я могу удалять элементы во время итерации?
Решение
Использовать УдалитьГде вместо этого метод HashSet:
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";
}
РЕДАКТИРОВАТЬ: Мне только что пришло в голову кое-что:поскольку HashSet — это набор, который не содержит повторяющихся значений, просто вызывается hashset.Remove("somestring")
будет достаточно.Нет необходимости делать это в цикле, поскольку никогда не будет более одного совпадения.
Другие советы
Вы не можете удалять элементы из коллекции, просматривая ее с помощью перечислителя.Два подхода к решению этой проблемы:
- Прокрутите коллекцию назад, используя обычный индексированный цикл for (который, я считаю, не является вариантом в случае
HashSet
) - Прокрутите коллекцию, добавьте элементы, которые нужно удалить, в другую коллекцию, затем пройдитесь по коллекции «подлежащей удалению» и удалите элементы:
Пример второго подхода:
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);
}
Я бы не стал использовать два цикла foreach — достаточно одного цикла foreach:
HashSet<string> anotherHashSet = new HashSet<string>();
foreach (var item in hashSet)
{
if (!shouldBeRemoved)
{
anotherSet.Add(item);
}
}
hashSet = anotherHashSet;
Обычно, когда я хочу что-то перебрать и удалить значения, я использую:
For (index = last to first)
If(ShouldRemove(index)) Then
Remove(index)