Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Merging dictionaries in C#

What's the best way to merge 2 or more dictionaries (Dictionary<T1,T2>) in C#? (3.0 features like LINQ are fine).

I'm thinking of a method signature along the lines of:

public static Dictionary<TKey,TValue>                  Merge<TKey,TValue>(Dictionary<TKey,TValue>[] dictionaries); 

or

public static Dictionary<TKey,TValue>                  Merge<TKey,TValue>(IEnumerable<Dictionary<TKey,TValue>> dictionaries); 

EDIT: Got a cool solution from JaredPar and Jon Skeet, but I was thinking of something that handles duplicate keys. In case of collision, it doesn't matter which value is saved to the dict as long as it's consistent.

like image 846
orip Avatar asked Nov 16 '08 17:11

orip


People also ask

Can I use two dictionaries to merge?

You can merge two dictionaries using the | operator. It is a very convenient method to merge dictionaries; however, it is only used in the python 3.9 version or more.

How do I merge one dictionary with another?

Dictionaries can also be merged by using the unpacking operator (**). It is a unary operator with a dict object as an operand. It adds each k-v pair in an empty dictionary. Obviously, if the second dictionary is also unpacked, the value of the existing key will be updated.

Which function helps merge dictionary?

Dictionary is also iterable, so we can use itertools. chain() to merge two dictionaries. The return type will be itertools.


2 Answers

This partly depends on what you want to happen if you run into duplicates. For instance, you could do:

var result = dictionaries.SelectMany(dict => dict)                          .ToDictionary(pair => pair.Key, pair => pair.Value); 

That will throw an exception if you get any duplicate keys.

EDIT: If you use ToLookup then you'll get a lookup which can have multiple values per key. You could then convert that to a dictionary:

var result = dictionaries.SelectMany(dict => dict)                          .ToLookup(pair => pair.Key, pair => pair.Value)                          .ToDictionary(group => group.Key, group => group.First()); 

It's a bit ugly - and inefficient - but it's the quickest way to do it in terms of code. (I haven't tested it, admittedly.)

You could write your own ToDictionary2 extension method of course (with a better name, but I don't have time to think of one now) - it's not terribly hard to do, just overwriting (or ignoring) duplicate keys. The important bit (to my mind) is using SelectMany, and realising that a dictionary supports iteration over its key/value pairs.

like image 153
Jon Skeet Avatar answered Sep 21 '22 03:09

Jon Skeet


I would do it like this:

dictionaryFrom.ToList().ForEach(x => dictionaryTo.Add(x.Key, x.Value)); 

Simple and easy. According to this blog post it's even faster than most loops as its underlying implementation accesses elements by index rather than enumerator (see this answer).

It will of course throw an exception if there are duplicates, so you'll have to check before merging.

like image 43
Jonas Stensved Avatar answered Sep 25 '22 03:09

Jonas Stensved