C # - удаление элементов из словаря в то время как цикл - PullRequest
5 голосов
/ 29 июня 2010

У меня есть это, и все, кажется, работает нормально, но не уверен, почему и если это действительно.

        Dictionary<string, List<string>> test = new Dictionary<string, List<string>>();

        while (test.Count > 0)
        {
            var obj = test.Last();
            MyMethod(obj);
            test.Remove(obj.Key);
        }

Обновление: спасибо за ответы, я обновил свой код, чтобы объяснить, почему я не делаю Dictionary.Clear ();

Ответы [ 9 ]

10 голосов
/ 29 июня 2010

Нет ничего плохого в том, чтобы поменять тип коллекции в цикле while таким образом.Проблемы возникают в том случае, когда вы изменяете коллекцию во время блока foreach.Или, в более общем случае, используйте IEnumerator<T> после того, как базовая коллекция видоизменена.

Хотя в этом примере было бы намного проще просто позвонить test.Clear():)

8 голосов
/ 01 июля 2010

Я не понимаю, почему вы пытаетесь обработать все записи Dictonary в обратном порядке - но ваш код в порядке.

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

EG:

var keys = test.Keys.OrderByDescending(o => o).ToList();

foreach (var key in keys)
{
    var obj = test[key];
    MyMethod(obj);
    test.Remove(key);
}

Диктонары быстры, когда к ним обращаются по значению ключа.Last () работает медленнее и подсчет не требуется - вы можете получить список всех (уникальных) ключей.

1 голос
/ 29 июня 2010

Это работает, потому что Count будет обновляться каждый раз, когда вы удаляете объект. Допустим, счетчик равен 3, test.Remove будет уменьшать счет до 2 и т. Д., Пока счетчик не станет равным 0, тогда вы выйдете из цикла

1 голос
/ 29 июня 2010

Это работает, хорошо, поскольку вы не перебираете словарь при удалении элементов. Каждый раз, когда вы проверяете test.Count, это похоже на проверку с нуля.

При этом вышеприведенный код можно было бы написать гораздо проще и эффективнее:

test.Clear();
0 голосов
/ 30 июня 2010

Несмотря на ваше обновление, вы, вероятно, все еще можете использовать clear ...

foreach(var item in test) {
  MyMethod(item);
}
test.Clear()

Ваш вызов .Last () будет чрезвычайно неэффективным в большом словаре и не гарантирует каких-либопорядок обработки независимо (словарь представляет собой неупорядоченную коллекцию)

0 голосов
/ 29 июня 2010

Кажется, это будет работать, но выглядит очень дорого.Это было бы проблемой, если бы вы перебирали его с помощью цикла foreach (вы не можете редактировать коллекции во время перебора).

Dictionary.Clear() должен добиться цели (но вы, вероятно, уже знали это).

0 голосов
/ 29 июня 2010

Итак, вы просто пытаетесь очистить словарь, правильно? Не могли бы вы просто сделать следующее?

Dictionary<string, List<string>> test = new Dictionary<string, List<string>>();
        test.Clear(); 
0 голосов
/ 29 июня 2010

Все, что вы делаете, это берете последний элемент в коллекции и удаляете его до тех пор, пока в словаре не останется больше элементов.

Ничего необычного, и нет никаких причин, по которым оно не должно работать (если вы хотите очистить коллекцию).

0 голосов
/ 29 июня 2010

Да, это должно быть правильно, но почему бы просто не позвонить Dictionary.Clear()?

...