2009-09-04 14 views
12

Czy istnieje dobry sposób w C#, aby naśladować następujące python składni:C# sposób naśladować Python słownik Składnia

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

Innymi słowy, chciałbym coś z [] Dostęp do stylu, który może powrócić albo inny słownik lub typ łańcucha, w zależności od tego, jak został ustawiony.

Próbowałem rozwiązać ten problem za pomocą niestandardowej klasy, ale nie wydaje się, aby odnieść sukces. Jakieś pomysły?

Dzięki!

Edytuj: Jestem zły, wiem. Rozwiązanie Jareda Par jest świetne. . . dla 2-poziomowego słownika tego formularza. Jednak jestem też ciekawy dalszych poziomów. . . na przykład:

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

I tak dalej. Jakieś pomysły na ten temat?

Edit 3:

Oto końcowy klasa I skończył przy użyciu:

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

Klasa ta działa dla nieskończonych szczeblach, i mogą być odczytywane z bez wyraźnej konwersji (niebezpieczny, może, ale hej).

Wykorzystanie tak:

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

Dziękuję bardzo Jared Par!

Odpowiedz

12

Możesz to osiągnąć poprzez posiadanie klasy, nazwijmy ją PythonDictionary, która jest zwracana od mydict["bc"] mają następujących członków.

  • Właściwość indekser aby umożliwić [ "de"] dostęp
  • niejawna konwersja z ciągiem do PythonDictionary

To powinno umożliwić obu przypadkach skompilować dobrze.

Na przykład

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

Bardzo ładnie wykonane. Nienawidzę tych niejawnych konwersji, ale z pewnością pozwala to robić to, co chce OP. –

+1

Doskonałe rozwiązanie dla 1 lub 2 kluczy. . . Podoba mi się to i prawdopodobnie zadziała w moim przypadku (bardzo dziękuję!). Jednak jestem też ciekawy głębszych słowników. Jakieś pomysły? –

+0

Tak, to było bardzo rozszerzalne. Wynikowa klasa jest pokazana w pytaniu. Dziękuję Ci bardzo! –

1

Dzięki za komentarz na to pytanie i rozdzielczości. Konwertowane na 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 

Zastosowanie:

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

Ta odpowiedź nie pasuje do polityki [so] (i została oznaczona jako taka), ponieważ nie odpowiada na pytanie OP (o C#.), Ale myślę, że dodaje wartości. Polecam * nie * należy usunąć. Zauważ jednak, że ktoś, kto szuka rozwiązania opartego tylko na VB, może nie pomyśleć o sprawdzeniu tego pytania. – jpaugh

+1

Po prostu próbuję przyczynić się. – jmjohnson85

+0

@ jmjhonson85 Szanuję to. Czytałem odpowiedź w kolejce do przeglądu, ponieważ została ona oznaczona. Mam tylko nadzieję, że dam wam ukłon w ziemi. – jpaugh