2012-04-05 74 views
3

如何使以下方法更具功能性 - linq-style?C#Linq合併兩個字典

public static Dictionary<T, T> MergeDict<T, T>(Dictionary<T, T> a, Dictionary<T, T> b) 
    { 
     var e = new Dictionary<T, T>(); 

     a.Concat(b).ToList().ForEach(pair => 
     { 
      e[pair.Key] = pair.Value; 
     }); 

     return e; 
    } 
+4

如果兩個詞典之間存在關鍵衝突,你打算做什麼? – 2012-04-05 19:37:26

+0

@ericj .:使用b的值 – michaelr524 2012-04-07 21:36:54

回答

8

要繼續你的重複丟棄方式,只需組合並在組中取得一個獲勝項目(如最後一個)。

first.Concat(second) 
    .GroupBy(kvp => kvp.Key, kvp => kvp.Value) 
    .ToDictionary(g => g.Key, g => g.Last()); 
+0

這實際上會有相反的行爲 - 值從「第一」將保持,OP將始終從「秒」(即:g.Last()或反向串聯)得到值 – 2012-04-05 19:43:52

+0

@ReedCopsey包含在編輯中,謝謝。 – 2012-04-05 19:46:08

+1

@davidb我認爲這是最優雅的解決方案 – michaelr524 2012-04-07 21:44:01

3

你可以ToDictionary直接使用:

public static Dictionary<T, T> MergeDict<T, T>(Dictionary<T, T> a, Dictionary<T, T> b) 
{ 
    return a.Concat(b).ToDictionary(kvp => kvp.Key, kvp => kvp.Value); 
} 

注意,這將提高在重複鍵的情況下例外。

如果您需要處理重複密鑰,則需要決定如何處理這個密鑰。例如,這會從「B」刪除重複項:

public static Dictionary<T, T> MergeDict<T, T>(Dictionary<T, T> a, Dictionary<T, T> b) 
{ 
    return a.Concat(b.Where(kvp => !a.ContainsKey(kvp.Key)).ToDictionary(kvp => kvp.Key, kvp => kvp.Value); 
} 

要獲得相同的行爲,原來,你可以走另外一條路(從「B」保持KeyValuePair值):

public static Dictionary<T, T> MergeDict<T, T>(Dictionary<T, T> a, Dictionary<T, T> b) 
{ 
    return b.Concat(a.Where(kvp => !b.ContainsKey(kvp.Key)).ToDictionary(kvp => kvp.Key, kvp => kvp.Value); 
} 
+0

對重複行爲表現不同。這個版本拋出。 – 2012-04-05 19:40:40

+0

@HenkHolterman是的 - 我編輯顯示如何避免... – 2012-04-05 19:41:26

+0

@reedcopsey看起來不錯,現在我想知道什麼是最有效的解決方案:) – michaelr524 2012-04-07 21:42:00

0

也許是這樣的。

public static IDictionary<T, U> Merge<T, U>(this IDictionary<T, U> first, IDictionary<T, U> second) 
{ 
    return first.Concat(second).ToDictionary(kvp => kvp.Key, kvp => kvp.Value); 
}