altandogan
altandogan

Reputation: 1285

Concat two dictionary with same key records

I want to merge two dictionaries. When I try this I get an error about duplicate keys. How can I merge two dictionaries which have the same keys?

class Program
{
    static void Main(string[] args)
    {
        Dictionary<Class1.Deneme, List<string>> dict1 = new Dictionary<Class1.Deneme, List<string>>();
        Dictionary<Class1.Deneme, List<string>> dict2 = new Dictionary<Class1.Deneme, List<string>>();
        Dictionary<Class1.Deneme, List<string>> dict3 = new Dictionary<Class1.Deneme, List<string>>();

        List<string> list1 = new List<string>() { "a", "b" };
        List<string> list2 = new List<string>() { "c", "d" };
        List<string> list3 = new List<string>() { "e", "f" };
        List<string> list4 = new List<string>() { "g", "h" };

        dict1.Add(Class1.Deneme.Buyer, list1);
        dict2.Add(Class1.Deneme.Buyer, list2);
        dict3 = dict1.Concat(dict2).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);

        Console.Read();
    }
}

public class Class1
{
    public enum Deneme
    { 
        Customer=1, 
        Buyer=2,
        Supplier=3
    }
}

Upvotes: 2

Views: 2170

Answers (2)

Jodrell
Jodrell

Reputation: 35716

how about

static IDictionary<TKey, TValue> Merge<TKey, TValue>(
    this IDictionary<TKey, TValue> left,
    IDictionary<TKey, TValue> right,
    Func<TKey, TValue, TValue, TValue> valueMerger)
{
    var result = new Dictionary<TKey, TValue>();
    foreach(var pair in left.Concat(right))
    {
        if (result.ContainsKey(pair.Key))
        {
            result[pair.Key] = valueMerger(
                                   pair.Key,
                                   pair.Value,
                                   result[pair.Key]);
            continue;
        }

        result.Add(pair.Key, pair.Value);
    }

    return result;
}

so, you'd need to supply a delegate to handle the case where keys are duplicated. Using your example I'd suggest,

var dictionary1 = new Dictionary<Class1.Deneme, List<string>>();
var dictionary2 = new Dictionary<Class1.Deneme, List<string>>();

var merged = dictionary1.Merge(
                 dictionary2,
                 (key, left, right) => left.Concat(right));

or perhaps you'd rather throw an exception?

   var merged = dictionary1.Merge(
                 dictionary2,
                 (key, left, right) => throw new ArgumentException("right", ...);

Upvotes: 2

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236248

Group all KeyValuePairs by key. Then convert these groups to dictionary by selecting group key as key and flattened values as value (you can also apply Distinct() before ToList() if you do not want duplicated strings):

dict1.Concat(dict2)
     .GroupBy(kvp => kvp.Key) // thus no duplicated keys will be added
     .ToDictionary(g => g.Key, g => g.SelectMany(kvp => kvp.Value).ToList());

Upvotes: 5

Related Questions