【问题标题】:Automatically creating a collection in the Dictionary<Key, Collection<Value>>在 Dictionary<Key, Collection<Value>> 中自动创建一个集合
【发布时间】:2011-01-10 18:01:39
【问题描述】:

很多时候我必须创建一个Dictionary&lt;KeyType, List&lt;ValueType&gt;&gt;

在我可以开始使用字典之前,我必须首先验证是否已为该键创建了 List。

//Can i remove these two lines?
if(!dict.ContainsKey(key)) 
    dict[key]= new List<ValueType>;

//now use the key
dict[key].Add(value);

我知道它只有“2 行”代码,但这让我很烦,我认为可以将其删除。

我可以以某种方式扩展字典,但在我这样做之前,我想知道是否有人找到了删除上述if 声明的聪明方法。

基本上我想创建一个Dictionary&lt;KeyType, Collection&lt;ValueType&gt;&gt; 并像dict[key].Add(value) 一样立即开始使用它。

【问题讨论】:

  • 如果我没有我的个人 C# 实用程序类,Multimap 是我编写的第一个类。希望他们尽快将其添加到标准类库中!

标签: c# .net collections dictionary


【解决方案1】:

查看在 .NET 3.5 中随 Linq 引入的 LookUp 类 - 它可能正是您要寻找的:类似 Dictionary 的类,每个键支持多个项目。

也许唯一显着的缺点是您必须在一批中提供所有元素,因为 LookUp 是不可变的。

【讨论】:

    【解决方案2】:

    您可以创建类似 Google Java Collection 的 Multimap... 或者您可以添加这样的扩展方法:

    public static void AddValue<TKey, TValue>
        (this IDictionary<TKey, List<TValue>> dictionary, TKey key, TValue value)
    {
        List<TValue> values;
        if (!dictionary.TryGetValue(key, out values))
        {
            values = new List<TValue>();
            dictionary.Add(key, values);
        }
        values.Add(value);
    }
    

    正如 Bevan 所说,Lookup 也可以提供帮助 - 但您只能使用 ToLookup 方法创建一个,并且之后无法修改它。在许多情况下,这是一件非常好的事情,但是如果您需要一个可变映射,那么您将需要类似上面的东西。

    【讨论】:

      【解决方案3】:

      要添加答案,您还可以添加一个更通用的扩展,该扩展接受委托进行实例化:

      public static TValue GetOrCreate<TKey, TValue>
          (this IDictionary<TKey, TValue> dict, 
                TKey key, 
                Func<TKey, TValue> getValue)
      {
          TValue value;
          if (!dict.TryGetValue(key, out value))
          {
              dict.Add(key, getValue(key));
          }
          return value;
      }
      

      然后你可以提供你喜欢的任何实例化方法:

      Dictionary<int, string> dict = new Dictionary<int, string>();
      string result = dict.GetOrCreate(5, i => i.ToString());
      

      【讨论】:

      • 嗯..这基本上是280Z28所说的。哦,废话。
      【解决方案4】:

      ConcurrentDictionary&lt;T,K&gt;.GetOrAdd 方法非常有用。

      private ConcurrentDictionary<string, ICollection<int>> _dictionary;
      
      private static ICollection<int> CreateEmptyList(string dummyKey)
      {
          return new List<int>();
      }
      
      private void AddValue(string key, int value)
      {
          ICollection<int> values = _dictionary.GetOrAdd(key, CreateEmptyList);
          values.Add(value);
      }
      

      编辑:这是一个如何将功能实现为IDictionary&lt;T,K&gt; (C# 3) 的扩展方法的示例:

      请注意,IDictionary&lt;TKey, TValue&gt; 通常不是线程安全的,因此如果您希望使用此扩展方法实现线程安全,则必须像其他操作一样手动实现它。

      public static TValue GetOrAdd<TKey, TValue>(
          this IDictionary<TKey, TValue> dictionary,
          TKey key,
          Func<TKey, TValue> valueFactory)
      {
          TValue value;
          if (!dictionary.TryGetValue(key, out value))
          {
              value = valueFactory(key);
              dictionary.Add(key, value);
          }
      
          return value;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-14
        相关资源
        最近更新 更多