C# C语言中包含列表的合并词典

C# C语言中包含列表的合并词典,c#,linq,dictionary,merge,C#,Linq,Dictionary,Merge,这与如何在C语言中合并两个字典有关。本文给出了一个优雅的Linq解决方案,这很酷 然而,这个问题与Dictionary有关,而我有一个Dictionary,其中的值是一个列表 我正在寻找合并词典的解决方案,需要满足以下要求: 如果Dictionary1包含与Dictionary2相同的键,则应合并它们的列表。您将得到一个新的键值对和共享键,以及两个字典中的组合列表。 如果Dictionary1包含Dictionary2不包含的键,则Dictionary1中的列表应成为值,反之亦然。 这在Linq

这与如何在C语言中合并两个字典有关。本文给出了一个优雅的Linq解决方案,这很酷

然而,这个问题与Dictionary有关,而我有一个Dictionary,其中的值是一个列表

我正在寻找合并词典的解决方案,需要满足以下要求:

如果Dictionary1包含与Dictionary2相同的键,则应合并它们的列表。您将得到一个新的键值对和共享键,以及两个字典中的组合列表。 如果Dictionary1包含Dictionary2不包含的键,则Dictionary1中的列表应成为值,反之亦然。
这在Linq中可能不可能实现,也可能值得用for循环之类的方式直接写出,但最好有一个优雅的解决方案。

困难在于处理关键冲突的合并

如果我们首先使用SelectMany展平所有输入字典,我们就可以按元素的键将它们分组

var result = dictionaries
    .SelectMany(dict => dict)
    .GroupBy(kvp => kvp.Key)
结果集包含组,其中每个组的键是原始词典中的键,组的内容是具有相同键的列表的IEnumerable。从这些组中,我们可以使用SelectMany的Select转换将所有列表合并为一个IEnumerable

然后,我们可以使用ToDictionary转换从中获取字典,将IEnumerable转换回列表


我建议您创建自己的扩展方法。它将更有效,更容易修改

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);
        }
    }

您只需要将解决方案中的项目合并部分更改为上一个问题。 对于对象,我们有:

.ToDictionary(group => group.Key, group => group.First())
i、 e.对于重复的项目,仅取第一个

但我们可以用这个:

.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());

如果您需要一些额外的列表合并逻辑,例如仅合并不同的项,您可以尝试使用不同的合并表达式。我首先承认,这并不是很漂亮,但对我来说很有效

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);

如何填充字典?更新了我的答案,包括如何填充字典变量。
.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());
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);