【问题标题】:C# - Removing Items from Dictionary in while loopC# - 在while循环中从字典中删除项目
【发布时间】:2011-03-09 18:52:27
【问题描述】:

我有这个,似乎一切正常,但不知道为什么以及它是否有效。

        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();

【问题讨论】:

    标签: c# .net .net-3.5 c#-3.0


    【解决方案1】:

    我使用此代码有条件地删除项目。

    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);
    }
              
    

    【讨论】:

    • 写-1的人请说明原因,以便我改进答案。
    【解决方案2】:

    我不明白您为什么要以相反的顺序处理所有字典条目 - 但您的代码没问题。

    获取所有键的列表并通过键处理条目可能会更快一些,而不是一次又一次地计数......

    例如:

    var keys = test.Keys.OrderByDescending(o => o).ToList();
    
    foreach (var key in keys)
    {
        var obj = test[key];
        MyMethod(obj);
        test.Remove(key);
    }
    

    字典在通过键值访问时速度很快。 Last() 速度较慢,无需计数 - 您可以获得所有(唯一)键的列表。

    【讨论】:

      【解决方案3】:

      尽管您进行了更新,但您可能仍然可以使用 clear...

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

      您对 .Last() 的调用在大型字典上效率极低,并且无论如何都不能保证任何特定的处理顺序(字典是无序集合)

      【讨论】:

        【解决方案4】:

        这似乎可行,但看起来非常昂贵。如果您使用foreach 循环对其进行迭代,这将是一个问题(您无法在迭代时编辑集合)。

        Dictionary.Clear() 应该可以解决问题(但您可能已经知道了)。

        【讨论】:

          【解决方案5】:

          所以,您只是想清除字典,对吗?您不能只执行以下操作吗?

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

          【讨论】:

            【解决方案6】:

            您所做的只是取出集合中的最后一项并将其删除,直到字典中没有其他项为止。

            没有什么不寻常的,也没有理由不工作(只要清空集合是您想要做的)。

            【讨论】:

              【解决方案7】:

              是的,这应该是有效的,但为什么不直接打电话给Dictionary.Clear()

              【讨论】:

                【解决方案8】:

                之所以有效,是因为每次删除对象时都会更新 Count。所以说 count 为 3,test.Remove 会将 count 减为 2,以此类推,直到 count 为 0,然后你就会跳出循环

                【讨论】:

                  【解决方案9】:

                  这很好,因为您在删除项目时没有遍历字典。每次检查 test.Count 时,就像是从头开始检查一样。

                  话虽如此,上面的代码可以写得更简单更有效:

                  test.Clear();
                  

                  【讨论】:

                    【解决方案10】:

                    以这种方式在 while 循环中改变集合类型并没有错。当您在 foreach 块期间对集合进行变异时,您会遇到麻烦。或更一般地,在基础集合发生突变后使用IEnumerator&lt;T&gt;

                    虽然在这个示例中,调用test.Clear() 会简单得多:)

                    【讨论】:

                      猜你喜欢
                      • 2014-06-28
                      • 2020-01-30
                      • 1970-01-01
                      • 2011-11-17
                      • 2013-04-22
                      • 1970-01-01
                      • 1970-01-01
                      • 2011-01-20
                      • 2012-06-27
                      相关资源
                      最近更新 更多