2009-09-04 10 views
12

C'è un buon modo in C# per imitare la seguente sintassi di Python:C# modo di imitare Python dizionario Sintassi

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

In altre parole, mi piacerebbe qualcosa con [] accesso stile che può restituire sia un'altra dizionario o un tipo di stringa, a seconda di come è stato impostato.

Ho cercato di risolvere questo problema con una classe personalizzata ma non riesco a riuscire. Qualche idea?

Grazie!

Modifica: Sono malvagio, lo so. La soluzione di Jared Par è fantastica. . . per un dizionario di 2 livelli di questo modulo. Tuttavia, sono anche curioso di ulteriori livelli. . . ad esempio,

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

E così via. Qualche idea al riguardo?

Edit 3:

Ecco la classe finale ho finito per usare:

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

Questa classe funziona per infiniti livelli, e può essere letto da senza conversione esplicita (pericoloso, forse, ma hey).

Uso in questo modo:

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

ringrazio molto Jared Par!

risposta

12

È possibile ottenere ciò mediante la classe, chiamiamolo PythonDictionary, che viene restituito da mydict["bc"] con i seguenti membri.

  • Una proprietà indicizzatore per consentire la [ "de"] accesso
  • Una conversione implicita da stringa a PythonDictionary

che dovrebbe consentire entrambi i casi per compilare bene.

Per esempio

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

molto ben fatto. Odio queste conversioni implicite, ma certamente ti permette di fare ciò che l'OP vuole. –

+1

Ottima soluzione per 1 o 2 chiavi. . . Mi piace per quello, e probabilmente funzionerebbe nel mio caso (quindi grazie mille!). Tuttavia, sono anche curioso di dizionari più profondi. Qualche idea lì? –

+0

Sì, era molto estensibile. La classe risultante è mostrata in questione. Grazie mille! –

1

Grazie per la pubblicazione di questa domanda e la risoluzione. Convertito 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 

Usage:

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

Questa risposta non si adatta perfettamente alla politica di [so] (e viene contrassegnata come tale), perché non risponde alla domanda dell'OP (su C#.) Ma penso che aggiunga valore. Lo raccomando * non * essere cancellato. Si noti, tuttavia, che qualcuno alla ricerca di una soluzione VB-only potrebbe non pensare di verificare questa domanda. – jpaugh

+1

Sto solo provando a contribuire. – jmjohnson85

+0

@ jmjhonson85 Lo rispetto. Ho letto la tua risposta in una coda di revisione, perché è stata contrassegnata. Spero solo di darti la disposizione della terra, per così dire. – jpaugh