2012-04-05 15 views
3

以下の方法をより機能的なlinq形式にするには?C#Linqは2つの辞書をマージする

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

2つのディクショナリの間にキーの衝突がある場合、どのような動作を想定していますか? –

+0

@ericj:bの値が使用されます。 – michaelr524

答えて

8

重複した廃棄方法を続けるには、グループ内で勝利したアイテム(最後のものなど)を受け取るだけです。

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

これは実際には逆の動作をします。 OPはいつも "second"(すなわち: 'g.Last()'またはreverse concat)から値を取得します。 –

+0

@ReedCopseyは編集、ありがとうございます。 –

+1

@davidbこれは最も洗練されたソリューションだと思います – michaelr524

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

重複に対して異なる動作をします。このバージョンはスローされます。 –

+0

@HenkHoltermanはい - それを回避する方法を示すために編集しました。 –

+0

@reedcopseyはよく見えますが、今は最も効率的な解決策が何かと思っています:) – michaelr524

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); 
} 
関連する問題