【问题标题】:Dictionary enumeration in C#C#中的字典枚举
【发布时间】:2010-10-15 04:21:36
【问题描述】:

如何枚举字典?

假设我使用foreach() 进行字典枚举。我无法更新foreach() 中的键/值对。所以我想要一些其他的方法。

【问题讨论】:

    标签: c# .net dictionary enumeration


    【解决方案1】:

    要枚举字典,您可以枚举其中的值:

    Dictionary<int, string> dic;
    
    foreach(string s in dic.Values)
    {
       Console.WriteLine(s);
    }
    

    或 KeyValuePairs

    foreach(KeyValuePair<int, string> kvp in dic)
    {
       Console.WriteLine("Key : " + kvp.Key.ToString() + ", Value : " + kvp.Value);
    }
    

    或钥匙

    foreach(int key in dic.Keys)
    {
        Console.WriteLine(key.ToString());
    }
    

    如果您希望更新字典中的项目,您需要稍有不同,因为您无法在枚举时更新实例。您需要做的是枚举一个未更新的不同集合,如下所示:

    Dictionary<int, string> newValues = new Dictionary<int, string>() { 1, "Test" };
    foreach(KeyValuePair<int, string> kvp in newValues)
    {
       dic[kvp.Key] = kvp.Value; // will automatically add the item if it's not there
    }
    

    要删除项目,请以类似的方式进行,枚举我们要删除的项目集合而不是字典本身。

    List<int> keys = new List<int>() { 1, 3 };
    foreach(int key in keys)
    {
       dic.Remove(key);
    }
    

    【讨论】:

    • 或者你可以枚举键。
    • 我希望枚举键比仅枚举值更常见(至少在我的经验中是这样),因为您可以很容易地找到键的值(即字典的重点)。
    • 这包括枚举但不包括更新。要更新,您需要使用以下方法之一...请参阅 spender 的回答。
    【解决方案2】:

    在回答“我无法在 foreach() 中更新值/键”问题时,您无法在枚举集合时对其进行修改。我会通过制作 Keys 集合的副本来解决这个问题:

    Dictionary<int,int> dic=new Dictionary<int, int>();
    
    //...fill the dictionary
    
    int[] keys = dic.Keys.ToArray();
    foreach (int i in keys)
    {
        dic.Remove(i);
    }
    

    【讨论】:

    • 不需要 .ToArray() AFAIK。 .Keys 返回一个 IEnumerable。
    • 当然,但是如果字典在循环中被更改,那么该枚举会发生什么?它肯定会改变吗?
    • 更改行:foreach(int i in keys) to foreach(int i in dic.keys) throws and InvalidOperationException, "collection was modified; enumeration operation may not execute."如上所述制作副本不会以这种方式失败。
    • 你仍然可以内联,只需添加 .ToArray()... 所以 foreach(int i in dic.Keys.ToArray())
    • 当然,你可以内联,但归根结底是一样的。在优化的发布二进制文件中,它可能无论如何都会被内联。在单独的行中,如果出现问题,调试起来会更容易。
    【解决方案3】:

    Foreach。有三种方法:您可以枚举Keys 属性、Values 属性或字典本身,它是KeyValuePair&lt;TKey, TValue&gt; 的枚举器。

    【讨论】:

      【解决方案4】:

      我刚刚回答了关于列表的相同(更新的)问题,所以对于字典也是如此。

      public static void MutateEach(this IDictionary<TKey, TValue> dict, Func<TKey, TValue, KeyValuePair<TKey, TValue>> mutator)
      {
          var removals = new List<TKey>();
          var additions = new List<KeyValuePair<TKey, TValue>>();
      
          foreach (var pair in dict)
          {
              var newPair = mutator(pair.Key, pair.Value);
              if ((newPair.Key != pair.Key) || (newPair.Value != pair.Value))
              {
                  removals.Add(pair.Key);
                  additions.Add(newPair);
              }
          }
      
          foreach (var removal in removals)
              dict.Remove(removal);
      
          foreach (var addition in additions)
              dict.Add(addition.Key, addition.Value);
      }
      

      请注意,我们必须在循环之外进行更新,因此我们不会在枚举字典时对其进行修改。这也检测到由于使两个键相同而导致的冲突 - 它会抛出(由于使用Add)。

      示例 - 使用 Dictionary&lt;string, string&gt; 将所有键设为小写并修剪所有值:

      myDict.MutateEach(key => key.ToLower(), value => value.Trim());
      

      如果键在小写时不是唯一的,则会抛出。

      【讨论】:

        猜你喜欢
        • 2011-07-31
        • 2022-01-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多