1

I am trying to write an merge extension methods for my dictionary.

I really like the solution Merging dictionaries in C#

I am trying to modify the above solution to update the dictionary item if key exits. I do not want to use Concurrent dictionary. Any ideas ?

public static void Merge<TKey, TValue>(this IDictionary<TKey, TValue> first, IDictionary<TKey, TValue> second)
        {
            if (second == null) return;
            if (first == null) first = new Dictionary<TKey, TValue>();
            foreach (var item in second)
            {
                if (!first.ContainsKey(item.Key))
                {
                    first.Add(item.Key, item.Value);
                }
                else
                {
                    **//I Need to perform following update . Please Help
                   //first[item.Key] = first[item.key] + item.Value**
                }
            }
        }
Community
  • 1
  • 1
Think
  • 261
  • 6
  • 13
  • You should provide some example inputs and the expected output. – Austin Salonen Feb 28 '13 at 22:04
  • It completely depends on what you mean by "merge" for an arbitrary `TValue`. Numeric types can merge in much different ways than, say, strings, or arbitrary objects. One option is to provide a `merge` delegate as a parameter, so that the caller can specify how values for duplicate keys should be merged. – dlev Feb 28 '13 at 22:05

1 Answers1

4

Well, if you want the result to contain both values you need some means of combining them. If you want to "Add" the values then you'll need to define some means of combining two items, because you can't know if TValue defines a + operator. One option is to pass it in as a delegate:

public static void Merge<TKey, TValue>(this IDictionary<TKey, TValue> first
    , IDictionary<TKey, TValue> second
    , Func<TValue, TValue, TValue> aggregator)
{
    if (second == null) return;
    if (first == null) throw new ArgumentNullException("first");
    foreach (var item in second)
    {
        if (!first.ContainsKey(item.Key))
        {
            first.Add(item.Key, item.Value);
        }
        else
        {
           first[item.Key] = aggregator(first[item.key], item.Value);
        }
    }
}

To call it would look like:

firstDictionary.Merge(secondDictionary, (a, b) => a + b);

Although it's also common for Merge operations like this to pick one of the two items to keep, either the first, or the second (note that you could do either using the above function, by using the appropriate aggregator implementation).

For example, to always keep the item in the first dictionary you can use:

firstDictionary.Merge(secondDictionary, (a, b) => a);

To always replace it with the second:

firstDictionary.Merge(secondDictionary, (a, b) => b);
Servy
  • 202,030
  • 26
  • 332
  • 449
  • Servy, Thank you very much for the solution. That was a very fast response. I really appreciate it. – Think Feb 28 '13 at 22:19