合并两个字典 Dictionary<string, Dictionary<string, Object>>

3
这与如何在C#中合并两个字典的问题有点相关。其中提供了一个优雅的Linq解决方案,非常棒。
然而,那个问题涉及到Dictionary,而我有一个值为Dictionary的字典。
我正在寻找合并两个Dictionary>的解决方案,并具有以下要求:
  • Without duplicating key in the dictionary result of two dictionary,
  • For each dictionary I think a grouping by KEY can be part of the solution but after ...

    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
请展示一下您尝试过的内容,这样我们才能在此基础上进行扩展。 - Daniel Hilgarth
@Ks_Hamza:你应该使用ToLookup而不是ToDictionary - leppie
@Ks_Hamza: a.Concat(b).ToLookup(c => c.Key, c => c.Value)(我想是这样) - leppie
4个回答

1

我不是很清楚你想要什么。这个代码尝试合并这两个字典:

    // 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("如何合并两个对象?我放弃了。") - 很好的尝试。我认为这正是这里所要求的。 - pescolino
如果a的“外部”键与b的“外部”键相同,则两个对应的值都是字典。如您所见,我将它们合并。但是当这两个字典共享一个“内部”键时,内部值的类型为object。没有办法合并两个一般对象。要做到这一点,就需要额外的东西,例如将类型object更改为新类型IMergeable,其中IMergeable接口应提供与另一个对象合并的方法。 - Jeppe Stig Nielsen
这可能是我的请求的解决方案,但我正在寻找一种不需要循环而只使用LINQ的解决方案。 - Ks_Hamza

0
 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 ...");
        }
    }

0
你应该先问自己一个问题:合并两个字典的结果是什么类型?如果它们共享相同的键,如何将值合并在一起?
可能会像这样:
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<string, Dictionary<string, object>>的字典将会变成一个Dictionary<string, IEnumerable<Dictionary<string, object>>>

然而,你的值是字典,所以你可能想要合并它们:

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<Dictionary<string, object>> 并将其转换为一个 Dictionary<string, IEnumerable<object>>。现在,您可以针对 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));

0

试试这个

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接