TMStackO
TMStackO

Reputation: 363

How to merge two dictionaries but on duplicate keys combine the values in C#?

I have two dictionaries each with the same structure.

Dictionary<string, List<int>> dictA
Dictionary<string, List<int>> dictB

I want to merge the two dictionaries in such a way that for each key if it exists in both dictA and dictB I combine the the two lists together and use that as the value otherwise it just gets included. eg:

("wow", {0,0,0})
("key", {1,2,3}) in A

("qwerty", {4,0,4})
("key", {4,5,6}) in B

becomes

("wow", {0,0,0})
("qwerty", {4,0,4})
("key", {1,2,3,4,5,6})

How would I go about doing this?

Upvotes: 2

Views: 2502

Answers (2)

MikeJ
MikeJ

Reputation: 1379

You can do it with linq but it's simple to do with just a couple foreach loops.

var dictA = new Dictionary<string, List<int>>
{
    { "wow", new List<int>{0,0,0} },
    { "key", new List<int>{1,2,3} }
};
var dictB = new Dictionary<string, List<int>>
{
    { "querty", new List<int>{4,0,4} },
    { "key", new List<int>{4,5,6} }
};

var merged = new Dictionary<string, List<int>>();

foreach(var kvp in dictA)
{
    merged.Add(kvp.Key, kvp.Value);

    if(dictB.TryGetValue(kvp.Key, out var inB))
    {
        kvp.Value.AddRange(inB);
        dictB.Remove(kvp.Key);
    }
}

foreach (var kvp in dictB)
    merged.Add(kvp.Key, kvp.Value);

Upvotes: 1

RoadRunner
RoadRunner

Reputation: 26315

You could first merge your dictionaries in a IEnumerable<KeyValuePair<string, List<int>>> by combining them with Concat. We do this because some keys may not exist in both dictionaries, and we want them included in the final merged result.

We can then group the keys with ToLookup, then create a final merged Dictionary<string, List<int>> with ToDictionary, ensuring that the inner grouped lists are flattened with SelectMany.

var dictA = new Dictionary<string, List<int>>
{
    { "wow", new List<int>{0,0,0} },
    { "key", new List<int>{1,2,3} }
};

var dictB = new Dictionary<string, List<int>>
{
    { "querty", new List<int>{4,0,4} },
    { "key", new List<int>{4,5,6} }
};

var merged = dictA
    .Concat(dictB)
    .ToLookup(kvp => kvp.Key, kvp => kvp.Value)
    .ToDictionary(group => group.Key, group => group.SelectMany(x => x).ToList());

foreach (var kvp in merged)
{
    Console.WriteLine($"{kvp.Key} -> {"{ " + string.Join(", ", kvp.Value) + " }"}");
}

Output:

wow -> { 0, 0, 0 }
key -> { 1, 2, 3, 4, 5, 6 }
querty -> { 4, 0, 4 }

Upvotes: 1

Related Questions