两个 Dictionaries<TKey, TValue> 的并集到 Dictionary<TKey, List<TValue>>

问题描述

我想找到两个字典的联合,它们可能包含相同的键,但不同的值。 如果两个字典中都存在键,那么我想将值(如果它们不同)合并到列表中。 如果 key 只存在于一个字典中,那么我想创建一个 List 并将该项目添加到其中。

例如:

var dict1 = new Dictionary<int,string>();
var dict2 = new Dictionary<int,string>();

dict1.Add(1,"a");
dict2.Add(1,"b");
dict1.Add(2,"c");

var resultDict = Combine(dict1,dict2);

结果字典将是 Dictionary 的类型,并将包含 { 1: ["a","b"],2: ["c"]}。

我能想到的最简单的解决方案是遍历键的联合并添加空列表,然后遍历两个字典并将所有值添加到给定键的列表中。

有没有什么好的、实用的解决方案来组合这两个字典?

解决方法

如果我想合并两个以上的字典怎么办?

您可以使用以下方法,该方法还展示了如何选择性地为键传递自定义比较器(例如,如果键是您想以不区分大小写的方式进行比较的字符串):

public static Dictionary<TKey,List<TValue>> Combine<TKey,TValue>(
    IEqualityComparer<TKey> comparer = null,params IDictionary<TKey,TValue>[] dictionaries)
{
    if (comparer == null) comparer = EqualityComparer<TKey>.Default;
    Dictionary<TKey,List<TValue>> result = new Dictionary<TKey,List<TValue>>(comparer);
    IEnumerable<TKey> allKeys = dictionaries.SelectMany(dict => dict.Keys).Distinct(comparer);
    foreach (TKey key in allKeys)
    {
        List<TValue> list = new List<TValue>();
        foreach (IDictionary<TKey,TValue> dict in dictionaries)
        {
            if (dict.TryGetValue(key,out TValue value)) list.Add(value);
        }
        result.Add(key,list);
    }

    return result;
}

如果要使用默认比较器,则为比较器传递 null:

Dictionary<int,List<string>> resultDict = Combine(null,dict1,dict2,dict3);