Итерация HashSet при удалении элементов в C#

StackOverflow https://stackoverflow.com/questions/1482234

  •  18-09-2019
  •  | 
  •  

Вопрос

У меня есть хэш-набор на 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)
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top