2011-02-04 90 views
19

我的問題已被標記爲這個問題的一個可能重複:How to combine two dictionaries without looping?結合兩個詞典與LINQ

我相信我的問題是不同的,因爲我是問如何將兩個字典以特定方式結合起來:我想所有項目從Dictionary1加上Dictionary1中所有不在Dictionary1中的項目(即密鑰不存在)。

我有兩本詞典是這樣的:

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; 

我想將它們合併成一個新的詞典(在技術上,它並不一定是一個字典,它可能只是的KeyValuePairs序列)等輸出包含來自d1的所有KeyValuePairs以及僅來自d2的KeyValuePairs,其密鑰未出現在d1中。

概念:

var d3 = d1.Concat(d2.Except(d1)) 

但是,這是給我所有的D1和D2元素。

似乎它應該是顯而易見的,但我必須失去一些東西。

+0

的可能的複製[如何添加2個詞典內容,而不循環在C#](http://stackoverflow.com/questions/712927/how-to-add-2-dicti onary-contents-without-in-c-sharp) – 2016-04-28 05:01:16

+1

這個問題不是這個問題的重複。這個問題是問如何組合兩個字典,d1和d2,使得生成的字典包含d1中的所有項目以及來自d2的所有項目,這些項目不在d1中。另一個問題是要求,而且答案解釋瞭如何在沒有任何額外條件的情況下合併兩本字典。 – wageoghe 2016-04-28 17:58:46

回答

33

默認情況下使用Except時,它使用默認的相等比較器,該比較器對KeyValuePair類型比較鍵和值。您可以改爲:

var d3 = d1.Concat(d2.Where(kvp => !d1.ContainsKey(kvp.Key))); 
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); 
} 
+0

謝謝!這是一個非常酷的方法,以及馬克的。我看到我可以使用IEqualityComparer,但我想知道是否有更簡單的方法。 – wageoghe 2011-02-04 23:21:49

7
var d3 = d1.Concat(d2.Where(kvp => ! d1.ContainsKey(kvp.Key))) 
      .ToDictionary(x => x.Key, x => x.Value); 

這是爲我工作。

1

使用另一種解決方案你自己IEqualityComparer像@bitxwise和@DaveShaw的答案,但沒有使用Except()這使得它有點簡單:

var d3 = d1.Concat(d2).Distinct(new MyComparer()); 
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 } }