tags:

views:

267

answers:

6

Hi,

As i know, the method to add values for dictionary as below.

    Dictionary<string, string> myDict = new Dictionary<string, string>();

    myDict.Add("a", "1");

If I declared "myDictDict" as the style below.

IDictionary<string, Dictionary<string, string>> myDictDict = new Dictionary<string, Dictionary<string, string>>();

myDictDict .Add("hello", "tom","cat"); ?// How to add value here.

thank you.

+4  A: 
IDictionary<string,Dictionary<string,string>> myDictDict = new Dictionary<string,Dictionary<string,string>>();
Dictionary<string,string> dict = new Dictionary<string, string>();
dict.Add ("tom", "cat");
myDictDict.Add ("hello", dict);
Gonzalo
Hi Gonzalo, Show the compiler error.D:\learning\TMP\CSConApp\CSConApp\Program.cs(55,9): error CS1502: The best overloaded method match for 'System.Collections.Generic.IDictionary<string,System.Collections.Generic.Dictionary<string,string>>.Add(string, System.Collections.Generic.Dictionary<string,string>)' has some invalid argumentsD:\learning\TMP\CSConApp\CSConApp\Program.cs(55,31): error CS1503: Argument '2': cannot convert from 'void' to 'System.Collections.Generic.Dictionary<string,string>'
Nano HE
Yes. This code will not work.
SLaks
True. Fixed it. Thanks.
Gonzalo
Simple style, and it is enough for me. thank you.
Nano HE
+1  A: 
IDictionary<string, Dictionary<string, string>> myDictDict = new Dictionary<string, Dictionary<string, string>>();

var subDict = new Dictionary<string, string>();
myDictDict .Add("hello", subDict ); 
subDict.Add("tom", "cat");
Ngu Soon Hui
+7  A: 

The proper way is like this:

// myDictDict is Dictionary<string, Dictionary<string, string>>
Dictionary<string, string> myDict;
string key = "hello";
if (!myDictDict.TryGetValue(key, out myDict)) {
    myDict = new Dictionary<string, string>();
    myDictDict.Add(key, myDict);
}
myDict.Add("tom", "cat");

This will extract the dictionary corresponding to the key (hello in your example) or create it if necessary and then will add the key/value pair to that dictionary. You could even extract this into an extension method.

static class Extensions {
    public static void AddToNestedDictionary<TKey, TNestedDictionary, TNestedKey, TNestedValue>(
        this IDictionary<TKey, TNestedDictionary> dictionary,
        TKey key,
        TNestedKey nestedKey,
        TNestedValue nestedValue
    ) where TNestedDictionary : IDictionary<TNestedKey, TNestedValue> {
        dictionary.AddToNestedDictionary(
            key,
            nestedKey,
            nestedValue,
            () => (TNestedDictionary)(IDictionary<TNestedKey, TNestedValue>)
                new Dictionary<TNestedKey, TNestedValue>());
    }

    public static void AddToNestedDictionary<TKey, TNestedDictionary, TNestedKey, TNestedValue>(
        this IDictionary<TKey, TNestedDictionary> dictionary,
        TKey key,
        TNestedKey nestedKey,
        TNestedValue nestedValue,
        Func<TNestedDictionary> provider
    ) where TNestedDictionary : IDictionary<TNestedKey, TNestedValue> {
        TNestedDictionary nested;
        if (!dictionary.TryGetValue(key, out nested)) {
            nested = provider();
            dictionary.Add(key, nested);
        }
        nested.Add(nestedKey, nestedValue);
    }
}

I left out guarding against null input to keep the idea clear. Usage:

myDictDict.AddToNestedDictionary(
    "hello",
    "tom",
    "cat",
    () => new Dictionary<string, string>()
);

or

myDictDict.AddToNesteDictionary("hello", "tom", "cat");
Jason
Probably best separated into a function.
Hamish Grubijan
You could make the function more generic (pun intended) by changing the outer dictionary to `IDictionary` and the inner dictionary to `TInnerDictionary where TInnerDictionary : IDictionary<TNestedKey, TNestedValue>, new()`.
SLaks
Hi Jason, Thanks for your details. I would study the function later.
Nano HE
Woooohoooo I personally would chose this answer as accepted.
Hamish Grubijan
@Jason +1 => for answer with extension method code, thanks. @SLaks +1 => for comment suggesting generic ideas, thanks.
BillW
+2  A: 

You can use C# 3's collection initializers, like this:

IDictionary<string, Dictionary<string, string>> myDictDict = new Dictionary<string, Dictionary<string, string>> {
    { "hello", new Dictionary<string, string> { "Tom", "Cat" } }
};

If the dictionary already exists, you can write

dict.Add("hello", new Dictionary<string, string> { "Tom", "Cat" });

Note that this will only work if hello isn't an existing key in the outer dictionary. If it might be, you should use Jason's answer.

SLaks
.NET 2.0 sitll be used at my laptop. thank you.
Nano HE
@SLaks, Please see my revised answer for correct syntax for using automatic collection initializers with this complex example of Dictionary<string, Dictionary<string, string>>
BillW
@Nano: Collection initializers are a feature of the compiler; you can use them even with .Net 2. (But only in Visual Studio 2008)
SLaks
+2  A: 

You can define an extension method like this :

static void Add(this IDictionary<string, Dictionary<string, string>> dict, string a, string b, string c){
    dict.Add(a, new Dictionary<string,string>(){{b,c}};
}

and then use it as :

myDictDict.Add("hello", "tom","cat");
missingfaktor
This will only work if there isn't an existing `a` in the outer dictionary. See Jason's answer.
SLaks
Jason's answer then! :)
missingfaktor
+2  A: 

To handle this the "simple" way : something like this :

    myDictDict.Add("some string", new Dictionary<string, string>());

    myDictDict["some string"].Add("another", "string");

To respond directly to the OP's test case : (note the edit added below reflects a desire to correct the syntax of SLaks's answer : code tested and validated against Framework 3.5 Client profile in VS 2010 Beta 2)

    // a simple case of creating an instance of a dictionary
    // of type <string, string>
    // and using .NET 3.0's (FrameWork => 3.5) collection initializer syntax
    Dictionary<string, string> twoStringDict = new Dictionary<string, string>()
    {
      {"key one", "value one"},
      {"key two", "value two"}, // note : an "extra" comma does not cause an error here
    };

    // more complex case as in the question on StackOverFlow
    // where dictionary is type <string, Dictionary<string, string>>
    // and using .NET 3.0's (FrameWork => 3.5) collection initializer syntax
    Dictionary<string, Dictionary<string, string>> myDictDict = new Dictionary<string, Dictionary<string, string>>()
    {
      { "key one",
            new Dictionary<string, string>() { { "innerKeyOne", "innerValueOne" }}},
      { "key two",
            new Dictionary<string, string>() { { "innerKeyTwo", "innerValueTwo" }}}
    };

    // syntax for adding another key value pair to the complex case
    myDictDict.Add("key three", new Dictionary<string, string>() { { "innerKeyThree", "innerValueThree" }});
BillW
@Gonzalo, sorry about that, I started to examine your first answer by testing it in .NET, and wrote my own answer during the period of time while you were probably posting your revision, so when I posted it, your revision was not current in my browser. Note I did not down-vote you. regards,
BillW
Collection Initializers were introduced by C# 3 and will work on any target framework.
SLaks