Merge two dictionaries Dictionary <string, dictionary <string, object >>
This refers to this question, on how to combine two dictionaries in C #. An elegant Linq solution is presented which is cool.
However, this question pertains to Dictionary<Object1, Object2>
, whereas I have a dictionary where the value is Dictionary<string, Object>
.
I am looking for a tow merge solution Dictionary<string, Dictionary<string, Object>>
with the following requirements:
- Without duplicating a key in a dictionary, the result of two dictionaries,
-
For each dictionary, I think the KEY grouping might be part of the solution, but after ...
internal static Dictionary<string, Dictionary<string, object>> OperationDic(Dictionary<string, Dictionary<string, object>> a, Dictionary<string, Dictionary<string, object>> b, string operation)` { switch (operation) { case "+": var result = a.Concat(b).GroupBy(d => d.Key).ToDictionary (d => d.Key, d => d.First().Value); return result; default: throw new Exception("Fail ..."); } }
source share
I'm not very clear about what you want. This is trying to combine two dictionaries:
// first copy everything from a var result = new Dictionary<string, Dictionary<string, object>>(a); // now check to see if we can add stuff from b foreach (var entryOuter in b) { Dictionary<string, object> existingValue; if (result.TryGetValue(entryOuter.Key, out existingValue)) { // there already an entry, see if we can add to it foreach (var entryInner in entryOuter.Value) { if (existingValue.ContainsKey(entryInner.Key)) throw new Exception("How can I merge two objects? Giving up."); existingValue.Add(entryInner.Key, entryInner.Value); } } else { // new entry result.Add(entryOuter.Key, entryOuter.Value); } } return result;
You might want to add checks for null
. a
, b
and existingValue
(if it exists) maybe null
.
source share
internal static Dictionary<string, Dictionary<string, object>> OperationDic(Dictionary<string, Dictionary<string, object>> a, Dictionary<string, Dictionary<string, object>> b, string operation) { var result = new Dictionary<string, Dictionary<string, object>>(a); switch (operation) { case "+": // now check to see if we can add stuff from b foreach (var entryOuter in b) { Dictionary<string, object> existingValue; if (result.TryGetValue(entryOuter.Key, out existingValue)) { Dictionary<string, object> Value = entryOuter.Value; result[entryOuter.Key] = existingValue.Concat(Value).GroupBy(d => d.Key).ToDictionary(d => d.Key, d => d.First().Value); } else { // new entry result.Add(entryOuter.Key, entryOuter.Value); } } return result; default: throw new Exception("FAIL ..."); } }
source share
The first question you should ask yourself is what type is the result of merging two dictionaries? How can values be combined if they have the same key?
It could be something like this:
public static Dictionary<TKey, IEnumerable<TValue>> Merge<TKey, TValue>(this IDictionary<TKey, TValue> this_, IDictionary<TKey, TValue> other) { return this_.Concat(other). // IEnumerable<KeyValuePair<TKey, TValue>> GroupBy(kvp => kvp.Key). // grouped by the keys ToDictionary(grp => grp.Key, grp => grp.Select(kvp => kvp.Value).Distinct()); }
So your two type dictionaries Dictionary<string, Dictionary<string, object>>
will go to Dictionary<string, IEnumerable<Dictionary<string, object>>>
.
However, your values are dictionaries, so you can combine them:
public static Dictionary<TKey, IEnumerable<TValue>> Flatten<TKey, TValue>(IEnumerable<Dictionary<TKey, TValue>> dictionaries) { return dictionaries.SelectMany(d => d.Keys).Distinct(). // IEnumerable<TKey> containing all the keys ToDictionary(key => key, key => dictionaries.Where(d => d.ContainsKey(key)). // find Dictionaries that contain the key Select(d => d.First(kvp => kvp.Key.Equals(key))). // select that key (KeyValuePair<TKey, TValue>) Select(kvp => kvp.Value)); // and the value }
This takes IEnumerable<Dictionary<string, object>>
and converts it to Dictionary<string, IEnumerable<object>>
. Now you can call this method for every dictionary value created Merge
.
The calls will be as follows:
Dictionary<string, IEnumerable<Dictionary<string, object>>> result1 = dic1.Merge(dic2); Dictionary<string, Dictionary<string, IEnumerable<object>>> result2 = dic1.Merge(dic2).ToDictionary(kvp => kvp.Key, kvp => Flatten(kvp.Value));
source share