Безопасно ли удалить из сортиста во время итерации

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

  •  01-10-2019
  •  | 
  •  

Вопрос

Мой вопрос - это безопасно для перечисления для удаления элемента от SORTEDLISTLIST?

SortedList<decimal, string> myDictionary;
// omitted code

IEnumerator<decimal, string> enum = myDictionary.GetEnumerator();

while(enum.MoveNext)
{
  // is it ok to remove here?
  myDictionary.Remove(enum.Current.Key);
}
Это было полезно?

Решение

Это бросит исключение - вы не можете изменить коллекцию во время итерации.

Если вы немного подумаете об этом, вы поймете, почему. Если добавить или удаление из коллекции было разрешено, вы больше не будете итерации по той же коллекции - у вас слишком много (добавление), либо недостаточно элементов (удаление).

Другие советы

Как уже говорилось, что вы хотите сделать, это невозможно. Тем не менее, альтернативное решение будет просто поддерживать список предметов, отмеченных для удаления, а затем удалить эти после слова. Я бы также выбрал foreach а не а. while петля, меньше кода, например

var removeList = new List<decimal>();
foreach (var item in myDictionary)
{
    // have a condition which indicates which items are to be removed
    if (item.Key > 1)
    {
        removeList.Add(item.Key);
    }
}

Или если вы просто пытаетесь извлечь элементы для удаления, используйте LINQ

var removeList = myDictionary.Where(pair => pair.Key > 1).Select(k => k.Key).ToList();

Тогда просто удалите их из списка.

// remove from the main collection
foreach (var key in removeList)
{
    myDictionary.Remove(key);
}

Операции по списку во время итераций не поддерживаются в целом. Ожидаемое поведение - бросить исключение, но даже если коллекция не может сделать это, вы не должны полагаться на эту работу правильно.

Сначала вы можете скопировать элементы в другой список, а затем повторить этот новый список элементов, которые будут изменены.

Нет. Неведомогательноеexcception брошено. Я согласен, что уже перечисленные предметы могут быть удалены, поскольку есть фиксированный индекс. Однако проблема следующая:

Реализация SOLTEDEDLIST не является достаточно умным, чтобы выяснить, что удаление не будет влиять на дальнейшее выполнение перечисленного. И держать его простым и выполнять хорошо, это не должно.

Как другие уже указали, это не будет работать. Однако, поскольку сборник является сортиристом, вы можете использовать метод снятия.

Этот метод имеет немного лучший профиль памяти, поскольку он не требует накладных расходов, в отличие от увеличения O (n), используя отдельный список для отслеживания удаления. Он также имел бы профиль производительности O (N ^ 2), а не (n ^ 2 * log (n)). Съемный метод снятия o (n), поскольку он должен выполнить копию массива. Способ удаления добавляет операцию o (log (n)), чтобы найти индекс, прежде чем внутренне вызова съемки. Все это, вероятно, не относится к вам, но полезно знать, если вы столкнулись с ситуациями, связанными с большим количеством «n».

var myDictionary = new SortedList<decimal, string>();

// omitted code

int i = 0;
while (myDictionary.Count > 0 && i < myDictionary.Count)
{
  if (/* predicate to use for removal */)
  {
    myDictionary.RemoveAt(i);
  }
  else
  {
    i++;
  }
}

Другое решение:

            int counter= MyDictionary.Count;
            if (counter == 0)
                return;

            for (int i = 0;  i < counter;i++)
            {
                KeyValuePair<MyIdentifier, MyValue> key = (KeyValuePair<MyIdentifier, MyValue>)MyDictionary.ToArray()[i];
                MyIdentifier identifier = null;

                if (key.Key != null)
                    identifier = key.Key as MyIdentifier;

                if (identifier != null)
                    if (MyCondition)
                    {
                        MyDictionary.Remove(identifier);
                        counter--;
                    }
            }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top