简体   繁体   English

C# - 在 while 循环中从字典中删除项目

[英]C# - Removing Items from Dictionary in while loop

I have this and all seems to work fine but not sure why and if its valid.我有这个,一切似乎都很好,但不确定为什么以及它是否有效。

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

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

Update: Thanks for the answers, I have updated my code to explain why I don't do Dictionary.Clear();更新:感谢您的回答,我已经更新了我的代码来解释为什么我不做 Dictionary.Clear();

There is nothing wrong with mutating a collection type in a while loop in this manner. 以这种方式在while循环中改变集合类型没有任何问题。 Where you get into trouble is when you mutate a collection during a foreach block. 你遇到麻烦的地方是你在foreach区块中改变一个集合。 Or more generally use a IEnumerator<T> after the underlying collection is mutated. 或者更IEnumerator<T>是在底层集合发生变异后使用IEnumerator<T>

Although in this sample it would be a lot simpler to just call test.Clear() :) 虽然在这个示例中,调用test.Clear() :)会简单得多

I don't understand why you are trying to process all Dictonary entries in reverse order - but your code is OK. 我不明白为什么你试图以相反的顺序处理所有Dictonary条目 - 但你的代码没问题。

It might be a bit faster to get a list of all Keys and process the entries by key instead of counting again and again... 获取所有密钥列表并按键处理条目而不是一次又一次地计数可能会快一点......

EG: 例如:

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

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

Dictonarys are fast when they are accessed by their key value. 当他们通过键值访问时,Dictonarys很快。 Last() is slower and counting is not necessary - you can get a list of all (unique) keys. Last()速度较慢,无需计数 - 您可以获得所有(唯一)键的列表。

That works, fine, since you're not iterating over the dictionary while removing items. 这很好,因为你在删除项目时没有迭代字典。 Each time you check test.Count, it's like it's checking it from scratch. 每次检查test.Count时,就像是从头开始检查它。

That being said, the above code could be written much simpler and more effectively: 话虽这么说,上面的代码可以写得更简单,更有效:

test.Clear();

It works because Count will be updated every time you remove an object. 它的工作原理是因为每次删除对象时都会更新Count。 So say count is 3, test.Remove will decriment the count to 2, and so on, until the count is 0, then you will break out of the loop 所以说计数是3,test.Remove会将计数记录为2,依此类推,直到计数为0,那么你将打破循环

是的,这应该是有效的,但为什么不调用Dictionary.Clear()

All you're doing is taking the last item in the collection and removing it until there are no more items left in the Dictionary. 您正在做的就是获取集合中的最后一项并将其删除,直到字典中没有剩余项目为止。

Nothing out of the ordinary and there's no reason it shouldn't work (as long as emptying the collection is what you want to do). 没有什么不寻常的,也没有理由它不应该工作(只要清空集合就是你想要做的)。

So, you're just trying to clear the Dictionary, correct? 所以,你只是想清除字典,对吗? Couldn't you just do the following? 你能不能做到以下几点?

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

This seems like it will work, but it looks extremely expensive. 这似乎可行,但看起来非常昂贵。 This would be a problem if you were iterating over it with a foreach loop (you can't edit collections while your iterating). 如果您使用foreach循环迭代它(在迭代时无法编辑集合),这将是一个问题。

Dictionary.Clear() should do the trick (but you probably already knew that). Dictionary.Clear()应该做的伎俩(但你可能已经知道了)。

Despite your update, you can probably still use clear... 尽管你的更新,你仍然可以使用明确...

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

Your call to .Last() is going to be extremely inefficient on a large dictionary, and won't guarantee any particular ordering of the processing regardless (the Dictionary is an unordered collection) 您对.Last()的调用在大型字典上效率极低,并且不保证处理的任何特定顺序(字典是无序集合)

I used this code to remove items conditionally.我使用此代码有条件地删除项目。

var dict = new Dictionary<String, float>
var keys = new String[dict.Count];
dict.Keys.CopyTo(keys, 0);

foreach (var key in keys) {
var v = dict[key];
if (condition) {
    dict.Remove(key);
}
          

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM