这与this question有关,关于如何在C#中合并两个词典。提出了一个优雅的Linq解决方案,很酷。
但是,这个问题与Dictionary<Object1, Object2>,
有关,而我有一个字典,其值为List<Object2>.
我正在寻找合并Dictionary<Object1, List<Object2>>,
以满足以下要求的解决方案:
List<Object2>
列表。您最终会得到一个带有共享密钥的新键值对,以及来自两个词典的组合列表。List<Object2>
列表应该成为值,反之亦然。这在Linq中可能是不可能的,或者用for循环等手写它可能是值得的,但是有一个优雅的解决方案会很好。
答案 0 :(得分:3)
我建议您创建自己的扩展方法。它将更有效,更容易修改。
public static void MergeDictionaries<OBJ1, OBJ2>(this IDictionary<OBJ1, List<OBJ2>> dict1, IDictionary<OBJ1, List<OBJ2>> dict2)
{
foreach (var kvp2 in dict2)
{
// If the dictionary already contains the key then merge them
if (dict1.ContainsKey(kvp2.Key))
{
dict1[kvp2.Key].AddRange(kvp2.Value);
continue;
}
dict1.Add(kvp2);
}
}
答案 1 :(得分:2)
困难在于处理关键冲突的合并。
如果我们首先使用SelectMany
展平所有输入词典,我们可以按键将元素组合在一起。
var result = dictionaries
.SelectMany(dict => dict)
.GroupBy(kvp => kvp.Key)
结果集包含组,其中每个组的键是原始词典中的键,组的内容是具有相同键的列表的IEnumerable<List<T>>
。在这些群组中,我们可以使用List<T>
转换IEnumerable<T>
将所有Select
合并为一个SelectMany
。
var result = dictionaries
.SelectMany(dict => dict)
.GroupBy(kvp => kvp.Key)
.Select(grp => new { Key = grp.Key, Items = grp.SelectMany(list => list)})
然后,我们可以使用ToDictionary
转换从中获取字典,将IEnumerable<T>
转换回List<T>
。
var result = dictionaries
.SelectMany(dict => dict)
.GroupBy(kvp => kvp.Key)
.Select(grp => new { Key = grp.Key, Items = grp.SelectMany(list => list)})
.ToDictionary(kip => kip.Key, kip => new List<T>(kip.Items));
更新以回复评论
您可以随意填充dictionaries
。我假设它是一种为您选择的IEnumerable<IDictionary<TKey, List<T>>>
和TKey
实现T
的类型。
最简单的方法是使用List<T>
,如下所示:
List<IDictionary<TKey, List<T>>> dictionaries
= new List<IDictionary<TKey, List<T>>>();
dictionaries.Add(dictionary1); // Your variable
dictionaries.Add(dictionary2); // Your variable
// Add any other dictionaries here.
// Code as above!
答案 2 :(得分:2)
您只需将解决方案中的项目合并部分更改为上一个问题。 对于对象,我们有:
.ToDictionary(group => group.Key, group => group.First())
即。对于重复的项目,只需要拿第一个。
但我们可以使用它:
.ToDictionary(group => group.Key, group => group.SelectMany(list => list).ToList());
连接列表。
所以,最后的表达式是
var result = dictionaries.SelectMany(dict => dict)
.ToLookup(pair => pair.Key, pair => pair.Value)
.ToDictionary(group => group.Key,
group => group.SelectMany(list => list).ToList());
如果您需要一些额外的列表合并逻辑(例如,只合并不同的项目),您可以尝试使用不同的合并表达式
答案 3 :(得分:1)
我会第一个承认这不是那么漂亮,但这对我有用。
var d1 = new Dictionary<string, List<string>>();
var d2 = new Dictionary<string, List<string>>();
d1["test"] = new List<string>() { "Stockholm", "Motala" };
d1["more"] = new List<string>() { "numerous", "populous", "bigger", "plentiful" };
d2["test"] = new List<string>() { "Washington", "Charlottesville" };
d2["less"] = new List<string>() { "insufficient", "small", "imperceptible" };
var intersect = (from key in d1.Keys.Intersect(d2.Keys) select new { Key = key, Value = new List<string>(d1[key].Concat(d2[key])) }).ToDictionary(d => d.Key, d => d.Value);
var merged = d1.Concat(d2).Where(d => !intersect.Keys.Contains(d.Key)).Concat(intersect).ToDictionary(d => d.Key, d => d.Value);