Randy Hall
Randy Hall

Reputation: 8137

Adding many rows to C# dictionary at once

If I instantiate a new Dictionary I can pass in many values:

Dictionary<string, string> data = new Dictionary<string, string>(){
    { "Key1", "Value1" },
    { "Key2", "Value2" },
    { "Key3", "Value3" },
    { "Key4", "Value4" },
    { "Key5", "Value5" },
}

However, if I already have a Dictionary, such as when it is passed in a parameter, I'm required to call Add for each key-value pair:

data.Add("Key1", "Value1");
data.Add("Key2", "Value2");
data.Add("Key3", "Value3");
data.Add("Key4", "Value4");
data.Add("Key5", "Value5");

I'm wondering if there's a "shorthand" method for adding in a large number of values to an existing Dictionary at one time - preferably natively? An authoritative "no" is welcome if that be the case.


Not as clean as I'm looking for, but these are the two alternatives I know.

This one allows passing many values at once, but requires creating a new Dictionary rather than updating the existing one:

Dictionary<string, string> newData = new Dictionary<string, string>(data)
{
    { "Key6", "Value6"},
    { "Key7", "Value7"},
    { "Key8", "Value8"},
};

It's also possible to create an extension method, but this still calls Add for each row:

public static void AddMany<Tkey, TValue>(this Dictionary<Tkey, TValue> dict, Dictionary<Tkey, TValue> toAdd)
{
    foreach(KeyValuePair<Tkey, TValue> row in toAdd)
    {
        dict.Add(row.Key, row.Value);
    }
}

Upvotes: 6

Views: 11274

Answers (3)

Prince Prasad
Prince Prasad

Reputation: 1678

You can make an extension to achieve this task.

 public static class DictionaryHelper
        {
            public static Dictionary<TKey, TValue> AddRange<TKey, TValue>(this Dictionary<TKey, TValue> destination, Dictionary<TKey, TValue> source)
            {
                if (destination == null) destination = new Dictionary<TKey, TValue>();
                foreach (var e in source)
                {
                    if (!destination.ContainsKey(e.Key))
                        destination.Add(e.Key, e.Value);
    
                    destination[e.Key] = e.Value;
                }
                return destination;
            }
        }

This is a generic function that will accept another dictionary.

Upvotes: 0

D Stanley
D Stanley

Reputation: 152566

An authoritative "no" is welcome if that be the case.

That be the case.

No, there is not an AddRange or equivalent because there is no practical way to add multiple items to a dictionary at one time. It makes sense for a List to add multiple items at once because they can get copied into the internal array in one command.

For a Dictionary, the hash code of each item must be computed to determine what "bucket" the value will get stored in, so there is by necessity a need to iterate over each item. Thus an AddRange method or its equivalent would at best be syntactic sugar. At worst, one would need to define what would happen if any item in the list already existed. Would it throw an exception? If so, would items that were added before the duplicate stay in the dictionary? If not, would it silently skip the item or replace the duplicate?

These are questions that have no intuitively correct answer and thus have not been pre-defined.

Upvotes: 11

Bill Tarbell
Bill Tarbell

Reputation: 5234

If you frequently need to add multiple items to your dictionary you could make an extension method

public static class DictionaryExtensions
{
  public static void AddRange<TKey, TValue>(this Dictionary<TKey, TValue> dic, List<KeyValuePair<TKey, TValue>> itemsToAdd)
  {
    itemsToAdd.ForEach(x => dic.Add(x.Key, x.Value));
  }
}

The above would be fine for bulk adding known-unique items. If you need to be concerned about dupes then you'd want to add sanity checks and perhaps return a list of bools to let you know which succeeded .. but at that point you might as well forego the extension method since much of the convenience would be lost.

Upvotes: 0

Related Questions