我的问题已被标记为此问题的可能重复:How to combine two dictionaries without looping?
我相信我的问题是不同的,因为我问的是如何以特定的方式组合两个词典:我希望Dictionary1中的所有项目加上Dictionary2中的所有项目(即不存在的键都不存在)在Dictionary1中。< / p>
我有两个这样的词典:
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;
我想将它们组合成一个新的Dictionary(从技术上讲,它不必是一个字典,它可能只是一个KeyValuePairs
的序列),以便输出包含所有KeyValuePairs
}来自d1,只有来自d2
的KeyValuePairs,其Key未出现在d1
中。
概念:
var d3 = d1.Concat(d2.Except(d1))
但是这给了我d1和d2的所有元素。
似乎很明显,但我必须遗漏一些东西。
答案 0 :(得分:36)
默认使用Except
时,它使用默认的相等比较器,KeyValuePair
类型比较键和值。你可以采用这种方法:
var d3 = d1.Concat(d2.Where(kvp => !d1.ContainsKey(kvp.Key)));
答案 1 :(得分:7)
var d3 = d1.Concat(d2.Where(kvp => ! d1.ContainsKey(kvp.Key)))
.ToDictionary(x => x.Key, x => x.Value);
这对我有用。
答案 2 :(得分:2)
Jon Skeet(像往常一样)有一个扩展方法,可以让你这样做:Can I specify my explicit type comparator inline?
答案 3 :(得分:2)
我不知道它是否是LinQ中的新功能,但这正是.Union()
所做的:
var d3 = d1.Union(d2);
当然,对于字典,您必须提供自定义相等比较器以仅匹配键:
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();
}
}
然后:
var d3 = d1.Union(d2, new KeyValuePairComparer<string, object>());
使用您的示例,输出将是(在C#交互式测试中):
> d1.Union(d2, new KeyValuePairComparer<string, object>())
UnionIterator { { "a", 1 }, { "b", 2 }, { "c", 3 }, { "e", 12 } }
注意区别:
> d2.Union(d1, new KeyValuePairComparer<string, object>())
UnionIterator { { "a", 11 }, { "e", 12 }, { "c", 13 }, { "b", 2 } }
答案 4 :(得分:1)
您也可以使用自己的IEqualityComparer
。示例如下:
public class MyComparer : IEqualityComparer<KeyValuePair<string,string>> {
public bool Equals(KeyValuePair<string, string> x, KeyValuePair<string, string> y) {
return x.Key.Equals(y.Key);
}
public int GetHashCode(KeyValuePair<string, string> obj) {
return obj.Key.GetHashCode();
}
}
...
Dictionary<string, string> d1 = new Dictionary<string, string>();
d1.Add("A", "B");
d1.Add("C", "D");
Dictionary<string, string> d2 = new Dictionary<string, string>();
d2.Add("E", "F");
d2.Add("A", "D");
d2.Add("G", "H");
MyComparer comparer = new MyComparer();
var d3 = d1.Concat(d2.Except(d1, comparer));
foreach (var a in d3) {
Console.WriteLine("{0}: {1}", a.Key, a.Value);
}
答案 5 :(得分:1)
在@bitxwise和@DaveShaw的答案中使用您自己的IEqualityComparer
的另一种解决方案,但不使用Except()
,这使得它更简单:
var d3 = d1.Concat(d2).Distinct(new MyComparer());