42

What is the best way to add multiple values to a Dictionary if I don't want to call ".Add()" multiple times.

Edit: I want to fill it after initiation! there are already some values in the Dictionary!

So instead of

    myDictionary.Add("a", "b");
    myDictionary.Add("f", "v");
    myDictionary.Add("s", "d");
    myDictionary.Add("r", "m");
    ...

I want to do something like this

 myDictionary.Add(["a","b"], ["f","v"],["s","d"]);

Is there a way to do so?

Amal K
  • 4,359
  • 2
  • 22
  • 44
LocalHorst
  • 1,048
  • 2
  • 11
  • 24

10 Answers10

50

You can use curly braces for that, though this only works for initialization:

var myDictionary = new Dictionary<string, string>
{
    {"a", "b"},
    {"f", "v"},
    {"s", "d"},
    {"r", "m"}
};

This is called "collection initialization" and works for any ICollection<T> (see link for dictionaries or this link for any other collection type). In fact, it works for any object type that implements IEnumerable and contains an Add method:

class Foo : IEnumerable
{
    public void Add<T1, T2, T3>(T1 t1, T2 t2, T3 t3) { }
    // ...
}

Foo foo = new Foo
{
    {1, 2, 3},
    {2, 3, 4}
};

Basically this is just syntactic sugar for calling the Add-method repeatedly. After initialization there are a few ways to do this, one of them being calling the Add-methods manually:

var myDictionary = new Dictionary<string, string>
    {
        {"a", "b"},
        {"f", "v"}
    };

var anotherDictionary = new Dictionary<string, string>
    {
        {"s", "d"},
        {"r", "m"}
    };

// Merge anotherDictionary into myDictionary, which may throw
// (as usually) on duplicate keys
foreach (var keyValuePair in anotherDictionary)
{
    myDictionary.Add(keyValuePair.Key, keyValuePair.Value);
}

Or as extension method:

static class DictionaryExtensions
{
    public static void Add<TKey, TValue>(this IDictionary<TKey, TValue> target, IDictionary<TKey, TValue> source)
    {
        if (source == null) throw new ArgumentNullException("source");
        if (target == null) throw new ArgumentNullException("target");

        foreach (var keyValuePair in source)
        {
            target.Add(keyValuePair.Key, keyValuePair.Value);
        }
    }
}

var myDictionary = new Dictionary<string, string>
    {
        {"a", "b"},
        {"f", "v"}
    };

myDictionary.Add(new Dictionary<string, string>
    {
        {"s", "d"},
        {"r", "m"}
    });
Caramiriel
  • 7,029
  • 3
  • 30
  • 50
  • 1
    No way to fill it after initiation? – LocalHorst May 09 '14 at 13:36
  • 3
    Just another for/foreach loop in combination with `Add`. This is just syntactic sugar for the add methods. There is no such thing as `AddRange` for `Dictionary` as keys need to be hashed anyway. – Caramiriel May 09 '14 at 13:37
7

This isn't exactly a duplicate question, but what you probably want is for there to be a Dictionary.AddRange() method. And here is why that doesn't exist:

Why doesn't Dictionary have AddRange?

"Range doesn't really have any meaning to an associative container."

But it might be a good idea to write your own .AddRange() method to the Dictionary class. It would essentially be a loop of .Add() calls though.

Community
  • 1
  • 1
catfood
  • 4,267
  • 5
  • 29
  • 55
  • 3
    What he probably wanted is `.AddMultiple()`, or `.AddMany()`, or whatever, i.e the "range" word, which implies integer indexes, is not what he wants. – Virus721 Aug 01 '19 at 10:28
4

You can do it at initialization like all other answer show, or you can combine it with this trick:

Dictionary<string, string> myDictionary = new Dictionary<string, string>();
Dictionary<string, string> secondDictionary = new Dictionary<string, string>()
{ 
    {"1", "a"}, 
    {"2", "b"} 
};
myDictionary = myDictionary.Union(secondDictionary)
                           .ToDictionary(kvp => kvp.Key, kvp => kvp.Value);

You have to make sure there are no duplicate keys or you will get an exception (but this ist the same with the Add method).

Raidri
  • 17,258
  • 9
  • 62
  • 65
  • 1
    `Union` will result in another `IEnumerable` which is not a dictionary anymore. This may also contain duplicate keys, since `KeyValuePair` does not implement equality/hashcode based on keys (say it created a dictionary). – Caramiriel May 09 '14 at 13:41
  • Added `ToDictionary` and a remark for duplicate keys. – Raidri May 09 '14 at 13:48
4

Although the question has been answered, I was curious if it would be possible to apply collection initializer-like syntax to a dictionary that was already initialized without the creation/overhead of creating a second dictionary to merge and throw away.

You can use (abuse?) Collection Initializers to add a range of values to an existing Dictionary after it's creation. How? By creating a helper class to do it:

public class AddRangeTo<TKey, TValue> : IEnumerable
{
    private readonly IDictionary<TKey, TValue> WrappedDictionary;

    public AddRangeTo(IDictionary<TKey, TValue> wrappedDictionary)
    {
        this.WrappedDictionary = wrappedDictionary;
    }

    public void Add(TKey key, TValue value)
    {
        this.WrappedDictionary.Add(key, value);
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        throw new NotSupportedException();
    }
}

With usage:

var myDictionary = new Dictionary<string, string>();

new AddRangeTo<string, string>(myDictionary)
{
    {"a", "b"},
    {"f", "v"},
    {"s", "d"},
    {"r", "m"}
};

Notice this allows you to add entries to the dictionary using a similar syntax but to a dictionary that's already been initialized. The part that kind of sucks is the repeat of the <string, string> generics, but that will not be necessary come C# 6.0. (EDIT: That is, in C# 6 it would look like new AddRangeTo(myDictionary)) (EDIT: This feature was scrapped from C# 6)

That all being said, I don't really recommend doing this necessarily. This is odd syntax/usage with unexpected side effects and I think might be confusing to others when they come across it. But if you find you would actually use this a lot and make your internal code easier to use and maintain, then bonus!

Chris Sinclair
  • 22,858
  • 3
  • 52
  • 93
3

You can do it like this:

var myDict = new Dictionary<string, string>() 
{
    {"a", "aa"},
    {"b", "bb"},
    {"c", "cc"},
    {"d", "dd"}
};
Mo Patel
  • 2,321
  • 4
  • 22
  • 37
Loetn
  • 3,832
  • 25
  • 41
2

This can be done out of the main code path in a way that allows you to reduce the clutter where it is happening using extension methods.

public static class DictionaryExtensions
{
  public static IDictionary<TKey,TValue> AddRange<TKey,TValue>(
               this IDictionary<TKey,TValue> source,
               params  KeyValuePair<TKey,TValue>[] items)
  {
    foreach (var keyValuePair in items)
    {
      source.Add(keyValuePair.Key, keyValuePair.Value);
    }
    return source;
  }
}
Josh Gallagher
  • 5,211
  • 2
  • 33
  • 60
Maslow
  • 18,464
  • 20
  • 106
  • 193
0

That would have been an easy google search: http://msdn.microsoft.com/en-us/library/bb531208.aspx. Anyways...here is the code:

Dictionary<string, string> myDictionary = new Dictionary<string, string>()
{
    { 'a', 'b' },
    { 'c', 'd' },
    { 'e', 'f' }
};

Of course, you can also write a loop or something to iterate over your values and calling the .add() method each time.

Bas Slagter
  • 9,831
  • 7
  • 47
  • 78
0

Well, you can on initialization:

new Dictionary<string, string> { {"a","b"}, {"f","v"},{"s","d"} }

This is called a collection initializer. When you want to add multiple items to an already existing dictionary, you can write a method.

Dennis_E
  • 8,751
  • 23
  • 29
-1

I have the perfect example for this initialization. Let's say you want to convert roman to integer. You receive a string with the roman number and you need a way to map what each character means. In c# you would use a dictionary with the characters and their equivalent integer

var map = new Dictionary<char, int>{
        {'M',1000},
        {'D',500},
        {'C',100},
        {'L',50},
        {'X',10},
        {'V',5},
        {'I',1}
    };
Diego
  • 24
  • 4
-2

myDictionary = new Dictionary() { {"a", 2) }, { "b", 3 }, };

amit kumar
  • 29
  • 5