2009-09-04 15 views
12

nachzuahmen Gibt es eine gute Möglichkeit, in C# die folgende Python-Syntax zu imitieren:C# Art und Weise Python Dictionary Syntax

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

Mit anderen Worten, ich möchte etwas mit [] Stil Zugang, die entweder eine andere zurückkehren Wörterbuch oder ein String-Typ, abhängig davon, wie es eingestellt wurde.

Ich habe versucht, dies mit einer benutzerdefinierten Klasse auszuarbeiten, kann aber nicht erfolgreich sein. Irgendwelche Ideen?

Danke!

Edit: Ich bin böse, ich weiß. Jared Pars Lösung ist großartig. . . für ein 2-Level-Wörterbuch dieser Form. Ich bin aber auch neugierig auf weitere Ebenen. . . zum Beispiel

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

Und so weiter. Irgendwelche Ideen dazu?

bearbeitet 3:

Hier ist die letzte Klasse I am Ende mit:

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

Diese Klasse für endlose Ebene funktioniert, und kann von ohne explizite Konvertierung (gefährlich, vielleicht gelesen, aber hey).

Verwendung wie folgt:

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

Vielen Dank Jared Par!

Antwort

12

Sie können dies erreichen, indem Sie die Klasse, nennen wir es PythonDictionary, die von mydict["bc"] zurückgegeben wird, haben die folgenden Mitglieder.

  • A Indexer-Eigenschaft für den [ "de"] Zugang
  • Eine implizite Konvertierung von String PythonDictionary ermöglichen

, dass beiden Fällen einfach gut kompilieren lassen soll.

Zum Beispiel

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

Sehr schön gemacht. Ich hasse diese impliziten Conversions, aber Sie können das tun, was das OP will. –

+1

Große Lösung für 1 oder 2 Schlüssel. . . Ich mag es dafür, und es würde wahrscheinlich in meinem Fall funktionieren (also vielen Dank!). Ich bin aber auch neugierig auf tiefere Wörterbücher. Irgendwelche Ideen da? –

+0

Yup, es war sehr erweiterbar. Die resultierende Klasse wird in Frage angezeigt. Vielen Dank! –

1

Vielen Dank für diese Frage und Auflösung veröffentlichen. Umgerechnet in 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 

Verbrauch:

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" 
+0

Diese Antwort passt nicht ganz in die Richtlinie von [so] (und wurde als solche gekennzeichnet), weil sie die Frage des OP (etwa C#) nicht beantwortet, aber ich denke, dass sie einen Mehrwert bringt. Ich empfehle es * nicht * gelöscht werden. Beachten Sie jedoch, dass jemand, der nach einer Nur-VB-Lösung sucht, diese Frage möglicherweise nicht prüft. – jpaugh

+1

Ich versuche nur beizutragen. – jmjohnson85

+0

@ jmjhonson85 Ich respektiere das. Ich habe Ihre Antwort in einer Überprüfungswarteschlange gelesen, da sie markiert wurde. Ich hoffe nur, dir sozusagen das Land zu geben. – jpaugh

Verwandte Themen