C#如何模仿Python字典语法

12

在C#中是否有一种好的方法来模仿以下Python语法:

mydict = {}
mydict["bc"] = {}
mydict["bc"]["de"] = "123";  # <-- This line
mydict["te"] = "5";          # <-- While also allowing this line
换句话说,我需要一些具有[]样式访问方式的东西,它可以根据设置方式返回另一个字典或字符串类型。我一直在尝试使用自定义类来解决这个问题,但似乎无法成功。有什么想法吗?谢谢!
编辑:我很恶毒,我知道。Jared Par的解决方案对于这种形式的两级字典非常好。然而,我也对更深层次的字典感到好奇...例如,
mydict["bc"]["df"]["ic"] = "32";

等等,你有什么想法吗?

编辑3:

这是我最终使用的类:

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;
}

这个类可以处理无限级别的操作,并且可以在没有显式转换的情况下读取(可能会有危险,但是嘿)。

使用方法如下:

        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";

非常感谢Jared Par!

2个回答

14

你可以通过让从mydict["bc"]返回的类(我们称之为PythonDictionary),具备以下成员来实现:

  • 索引器属性,允许使用 ["de"] 访问
  • 从字符串到 PythonDictionary 的隐式转换

这将使得两种情况都能够正常编译。

例如:

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";
}

做得非常好。我讨厌这些隐式转换,但它确实让你做到了 OP 想要的事情。 - Anderson Imes
1
对于1或2个键来说,这是一个很好的解决方案……我喜欢它,对我的情况可能也适用(非常感谢!)。然而,我对更深层次的字典也很好奇。有什么想法吗? - Walt W
是的,它非常易于扩展。结果类在问题中显示。非常感谢! - Walt W

2

感谢您发布这个问题和解决方案。转换为VB.NET:

Public Class PythonDict
    ' Public properties and conversions
    Default Public Property Item(ByVal index As String) As PythonDict
        Get
            Return Me.dict_(index)
        End Get

       Set(value As PythonDict)
            Me.dict_(index) = value
       End Set
    End Property

    Public Shared Narrowing Operator CType(value As String) As PythonDict
       Return New PythonDict(value)
    End Operator

    Public Shared Widening Operator CType(value As PythonDict) As String
       Return value.str_
    End Operator

    ' Public methods
    Public Sub New()
       Me.dict_ = New Dictionary(Of String, PythonDict)()
    End Sub

    Public Sub New(value As String)
       Me.str_ = value
    End Sub

    Public Function isString() As Boolean
       Return (Me.str_ IsNot Nothing)
    End Function

    ' Private fields
    Private dict_ As Dictionary(Of String, PythonDict) = Nothing
    Private str_ As String = Nothing
End Class

使用方法:

Dim s As PythonDict = New PythonDict()
s("Hello") = New PythonDict()
s("Hello")("32") = "hey there"
s("Hello")("34") = New PythonDict()
s("Hello")("34")("Section") = "Your face"
Dim result As String = s("Hello")("34")("Section")
s("Hi there") = "hey"

这个回答不太符合[so]的政策(并因此被标记),因为它没有回答OP的问题(关于C#)。但我认为它增加了价值。我建议删除它。请注意,然而,寻找仅VB解决方案的人可能不会想到检查这个问题。 - jpaugh
1
只是想做出贡献。 - jmjohnson85
@jmjhonson85 我很尊重你的看法。我在审核队列中读到了你的答案,因为它被标记了。我只是希望给你一个大致的情况。 - jpaugh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接