views:

193

answers:

1

Hi,

Is there a good way in C# to mimic the following python syntax:

mydict = {}
mydict["bc"] = {}
mydict["bc"]["de"] = "123";  # <-- This line
mydict["te"] = "5";          # <-- While also allowing this line

In other words, I'd like something with [] style access that can return either another dictionary or a string type, depending on how it has been set.

I've been trying to work this out with a custom class but can't seem to succeed. Any ideas?

Thanks!

Edit: I'm being evil, I know. Jared Par's solution is great . . . for a 2-level dictionary of this form. However, I am also curious about further levels . . . for instance,

mydict["bc"]["df"]["ic"] = "32";

And so on. Any ideas about that?

Edit 3:

Here is the final class I ended up using:

class PythonDict {
    /* Public properties and conversions */
    public PythonDict this[String index] {
        get {
            return this.dict_[index];
        }
        set {
            this.dict_[index] = value;
        }
    }

    public static implicit operator PythonDict(String value) {
        return new PythonDict(value);
    }

    public static implicit operator String(PythonDict value) {
        return value.str_;
    }

    /* Public methods */
    public PythonDict() {
        this.dict_ = new Dictionary<String, PythonDict>();
    }

    public PythonDict(String value) {
        this.str_ = value;
    }

    public bool isString() {
        return (this.str_ != null);
    }

    /* Private fields */
    Dictionary<String, PythonDict> dict_ = null;
    String str_ = null;
}

This class works for infinite levels, and can be read from without explicit conversion (dangerous, maybe, but hey).

Usage like so:

        PythonDict s = new PythonDict();
        s["Hello"] = new PythonDict();
        s["Hello"]["32"] = "hey there";
        s["Hello"]["34"] = new PythonDict();
        s["Hello"]["34"]["Section"] = "Your face";
        String result = s["Hello"]["34"]["Section"];
        s["Hi there"] = "hey";

Thank you very much Jared Par!

+8  A: 

You can achieve this by having the class, lets call it PythonDictionary, which is returned from mydict["bc"] have the following members.

  • A indexer property to allow for the ["de"] access
  • A implicit conversion from string to PythonDictionary

That should allow both cases to compile just fine.

For example

public class PythonDictionary {
    public string this[string index] {
        get { ... }
        set { ... }
    }
    public static implicit operator PythonDictionary(string value) {
        ...
    }
}

public void Example() {
    Dictionary<string, PythonDictionary> map = new Dictionary<string, PythonDictionary>();
    map["42"]["de"] = "foo";
    map["42"] = "bar";
}
JaredPar
Very nicely done. I hate these implicit conversions, but it certainly lets you do what the OP wants.
Anderson Imes
Great solution for 1 or 2 keys . . . I like it for that, and it would probably work in my case (so thank you very much!). However, I am also curious about deeper dictionaries. Any ideas there?
Walt W
Yup, it was very much extendible. Resulting class is shown in question. Thank you very much!
Walt W