将两个词典与LINQ结合使用

wag*_*ghe 23 .net c# linq dictionary

我的问题被标记为这个问题的可能重复:如何在没有循环的情况下组合两个词典?

我相信我的问题是不同的,因为我问的是如何以特定的方式组合两个词典:我希望Dictionary1中的所有项目加上Dictionary2中不存在的所有项目(即密钥不存在).

我有两个这样的词典:

var d1 = new Dictionary<string,object>();
var d2 = new Dictionary<string,object>();

d1["a"] = 1;
d1["b"] = 2;
d1["c"] = 3;

d2["a"] = 11;
d2["e"] = 12;
d2["c"] = 13;
Run Code Online (Sandbox Code Playgroud)

我想将它们组合成一个新的词典(从技术上讲,它不必是一个字典,它可能只是一个序列KeyValuePairs),以便输出包含所有KeyValuePairs来自d1和只有KeyValuePairs,d2其Key不会出现在d1.

概念:

var d3 = d1.Concat(d2.Except(d1))
Run Code Online (Sandbox Code Playgroud)

但这给了我d1和d2的所有元素.

似乎它应该是显而易见的,但我必须遗漏一些东西.

Mar*_*ers 36

Except默认使用时,它使用默认的相等比较器,该KeyValuePair类型比较键和值.你可以这样做:

var d3 = d1.Concat(d2.Where(kvp => !d1.ContainsKey(kvp.Key)));
Run Code Online (Sandbox Code Playgroud)


Thi*_*ire 8

嗯,我不知道这是否是 LinQ 中的一个新功能,但这正是.Union()

var d3 = d1.Union(d2);
Run Code Online (Sandbox Code Playgroud)

当然,对于字典,您必须提供自定义相等比较器以仅匹配键:

class KeyValuePairComparer<TKey, TValue> : IEqualityComparer<KeyValuePair<TKey, TValue>>
{
    public bool Equals(KeyValuePair<TKey, TValue> x, KeyValuePair<TKey, TValue> y)
    {
        return x.Key.Equals(y.Key);
    }
    public int GetHashCode(KeyValuePair<TKey, TValue> x)
    {
        return x.GetHashCode();
    }
}
Run Code Online (Sandbox Code Playgroud)

进而 :

var d3 = d1.Union(d2, new KeyValuePairComparer<string, object>());
Run Code Online (Sandbox Code Playgroud)

对于您的示例,输出将是(在 C# 交互中测试):

> d1.Union(d2, new KeyValuePairComparer<string, object>())
UnionIterator { { "a", 1 }, { "b", 2 }, { "c", 3 }, { "e", 12 } }
Run Code Online (Sandbox Code Playgroud)

注意区别:

> d2.Union(d1, new KeyValuePairComparer<string, object>())
UnionIterator { { "a", 11 }, { "e", 12 }, { "c", 13 }, { "b", 2 } }
Run Code Online (Sandbox Code Playgroud)


SP0*_*007 7

var d3 = d1.Concat(d2.Where(kvp => ! d1.ContainsKey(kvp.Key)))
           .ToDictionary(x => x.Key, x => x.Value);
Run Code Online (Sandbox Code Playgroud)

这对我有用.