【问题标题】:merge two dictionaries Dictionary<string, Dictionary<string, Object>>合并两个字典 Dictionary<string, Dictionary<string, Object>>
【发布时间】:2013-01-28 21:05:09
【问题描述】:

这有点与这个问题有关,关于如何在 C# 中合并两个字典。提出了一个优雅的 Linq 解决方案,很酷。

然而,这个问题与Dictionary&lt;Object1, Object2&gt; 相关,而我有一本字典,其中的值为Dictionary&lt;string, Object&gt;

我正在寻找合并两个Dictionary&lt;string, Dictionary&lt;string, Object&gt;&gt; 的解决方案,具有以下要求:

  • 两个字典的字典结果中没有重复键,
  • 对于每个字典,我认为按 KEY 分组可以成为解决方案的一部分,但在 ...

    internal static Dictionary<string, Dictionary<string, object>> OperationDic(Dictionary<string, Dictionary<string, object>> a, Dictionary<string, Dictionary<string, object>> b, string operation)`
        { 
            switch (operation) 
            {
                case "+":
                    var result =  a.Concat(b).GroupBy(d => d.Key).ToDictionary (d => d.Key, d => d.First().Value); 
                    return result;               
                default: 
    
                    throw new Exception("Fail ...");
            }             
        }
    

【问题讨论】:

  • 我已经被卡住了,我尝试了任何方法,但我仍在寻找
  • 请向我们展示您的尝试,以便我们对其进行扩展。
  • @Ks_Hamza:你应该使用ToLookup 而不是ToDictionary
  • @Ks_Hamza: a.Concat(b).ToLookup(c =&gt; c.Key, c =&gt; c.Value)(我认为)

标签: c# dictionary merge


【解决方案1】:

你应该问自己的第一个问题:合并两个字典的结果有什么类型?如果它们共享相同的键,如何将值合并在一起?

可能是这样的:

public static Dictionary<TKey, IEnumerable<TValue>> Merge<TKey, TValue>(this IDictionary<TKey, TValue> this_, IDictionary<TKey, TValue> other)
{
    return this_.Concat(other).     // IEnumerable<KeyValuePair<TKey, TValue>>
        GroupBy(kvp => kvp.Key).    // grouped by the keys
        ToDictionary(grp => grp.Key, grp => grp.Select(kvp => kvp.Value).Distinct());
}

所以Dictionary&lt;string, Dictionary&lt;string, object&gt;&gt; 类型的两个字典将转到Dictionary&lt;string, IEnumerable&lt;Dictionary&lt;string, object&gt;&gt;&gt;

但是,您的值是字典,因此您可能需要合并它们:

public static Dictionary<TKey, IEnumerable<TValue>> Flatten<TKey, TValue>(IEnumerable<Dictionary<TKey, TValue>> dictionaries)
{
    return dictionaries.SelectMany(d => d.Keys).Distinct().         // IEnumerable<TKey> containing all the keys
        ToDictionary(key => key,
            key => dictionaries.Where(d => d.ContainsKey(key)).     // find Dictionaries that contain the key
                Select(d => d.First(kvp => kvp.Key.Equals(key))).   // select that key (KeyValuePair<TKey, TValue>)
                Select(kvp => kvp.Value));                          // and the value
}

这需要IEnumerable&lt;Dictionary&lt;string, object&gt;&gt; 并将其转换为Dictionary&lt;string, IEnumerable&lt;object&gt;&gt;。您现在可以为 Merge 生成的字典的每个值调用此方法。

电话是:

Dictionary<string, IEnumerable<Dictionary<string, object>>> result1 = dic1.Merge(dic2);
Dictionary<string, Dictionary<string, IEnumerable<object>>> result2 = dic1.Merge(dic2).ToDictionary(kvp => kvp.Key, kvp => Flatten(kvp.Value));

【讨论】:

    【解决方案2】:
     internal static Dictionary<string, Dictionary<string, object>> OperationDic(Dictionary<string, Dictionary<string, object>> a, Dictionary<string, Dictionary<string, object>> b, string operation)
        {
            var result = new Dictionary<string, Dictionary<string, object>>(a);
            switch (operation)
            {
                case "+":                  
                // now check to see if we can add stuff from b
                foreach (var entryOuter in b)
                {
                  Dictionary<string, object> existingValue;
                  if (result.TryGetValue(entryOuter.Key, out existingValue))
                  {
                      Dictionary<string, object> Value = entryOuter.Value;
                      result[entryOuter.Key] = existingValue.Concat(Value).GroupBy(d => d.Key).ToDictionary(d => d.Key, d => d.First().Value);
                  }
                  else
                  {
                    // new entry
                    result.Add(entryOuter.Key, entryOuter.Value);
                  }
                }
                return result;
                default:                    
                    throw new Exception("FAIL ...");
            }
        }
    

    【讨论】:

      【解决方案3】:

      我不太清楚你想要什么。这试图合并两个字典:

          // first copy everything from a
          var result = new Dictionary<string, Dictionary<string, object>>(a);
      
          // now check to see if we can add stuff from b
          foreach (var entryOuter in b)
          {
            Dictionary<string, object> existingValue;
            if (result.TryGetValue(entryOuter.Key, out existingValue))
            {
              // there's already an entry, see if we can add to it
              foreach (var entryInner in entryOuter.Value)
              {
                if (existingValue.ContainsKey(entryInner.Key))
                  throw new Exception("How can I merge two objects? Giving up.");
                existingValue.Add(entryInner.Key, entryInner.Value);
              }
            }
            else
            {
              // new entry
              result.Add(entryOuter.Key, entryOuter.Value);
            }
          }
      
          return result;
      

      您可能想要为null 添加检查。 abexistingValue(如果存在)可能是 null

      【讨论】:

      • throw new Exception("How can I merge two objects? Giving up.") - 不错的尝试。我认为这正是这里所要求的。
      • @pescolino 如果a 的“外部”键与b 的“外部”键相同,则对应的两个值就是字典。如您所见,我将它们合并。但是当这两个字典共享一个“内部”键时,内部值的类型为object。没有办法合并两个通用对象。要做到这一点,你必须需要一些额外的东西,例如。将类型object 更改为新类型IMergeable,其中IMergeable 接口应提供与另一个对象合并的方法。
      • 这可能是我的要求的解决方案,但我正在寻找一个解决方案,而不是仅仅放弃 linq
      【解决方案4】:

      试试这个

      var 结果 = a.Concat(b).GroupBy(c => c.Key).ToDictionary>(

      【讨论】:

        猜你喜欢
        • 2012-03-01
        • 2014-12-03
        • 2014-10-22
        • 1970-01-01
        • 2012-05-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-06-17
        相关资源
        最近更新 更多