2009-05-15 3 views
5

ich passieren diese Art von Struktur zu verwenden, eine ganze Menge:Wie kann ich den Schmerz der Initialisierung von Wörterbüchern von Listen in C# erleichtern?

Dictionary<string, List<string>> Foo = new Dictionary<string, List<string>>(); 

, die zu dieser Art von Code führt:

foreach (DataRow dr in ds.Tables[0].Rows) 
{ 
    List<string> bar; 
    if (!Foo.TryGetValue(dr["Key"].ToString(), out desks)) 
    { 
     bar= new List<string>(); 
     Foo.Add(dr["Key"].ToString(), bar); 
    } 
    bar.Add(dr["Value"].ToString()); 
} 

Glauben Sie, es lohnt sich eine benutzerdefinierte DictionaryOfList Klasse zu schreiben, die damit umgehen würde Art von Dingen automatisch?

Gibt es eine andere Möglichkeit, diese Listen zu initialisieren?

foreach (DataRow dr in ds.Tables[0].Rows) 
{ 
    Foo.GetValueOrCreateDefault(dr["Key"]).Add(dr["Value"].ToString()) 
} 

Vielleicht können Sie auch eine Erweiterungsmethode für die gesamte Initialisierung schreiben: GetValueOrCreateDefault() oder so ähnlich -

+0

Was ein bisschen was tun Sie diese Struktur nützlich für? Da ich ein ziemlich neuer Programmierer bin, denke ich, dass ich die Wörterbuchstruktur noch nicht so oft benutzen kann! – RYFN

+0

Framework Version Info wäre nützlich, LINQ könnte dies viel sauberer – AnthonyWJones

+0

@Anthony: In der Tat. editierte Tags zu erwähnen. Net3.5 – Brann

Antwort

7

Sie können eine Erweiterungsmethode schreiben?

+0

Schöne Lösung, aber ich würde weiter gehen und eine Erweiterungsmethode erstellen Dictionary .AddPair (TKey, TValue). Dies wird viel einfacher zu lesen und zu verstehen sein, wenn jemand anders über den Code schauen muss. –

2

denke ich folgendes tun sollten:

class DictionaryOfList : Dictionary<string, List<string>> {} 
  • Bearbeiten Ich sollte mehr richtig lesen. Dies beantwortet die Frage nicht. Tanascius hat eine saubere Lösung geliefert.
+0

Danke, das ist praktisch! – Nick

4

Ein Wörterbuch einer Liste ... in .NET 3.5 wäre das ein ILookup<TKey,TValue>. Die Standardimplementierung (Lookup<TKey,TValue>) ist unveränderlich, aber ich schrieb eine EditableLookup<TKey,TValue> für MiscUtil. Das wird viel einfacher zu bedienen sein - dh Methode

var data = new EditableLookup<string, int>(); 
data.Add("abc",123); 
data.Add("def",456); 
data.Add("abc",789); 

foreach(int i in data["abc"]) { 
    Console.WriteLine(i); // 123 & 789 
} 

Other than that, eine Erweiterung:

public static void Add<TKey, TList, TValue>(
    this IDictionary<TKey, TList> lookup, 
    TKey key, TValue value) 
    where TList : class, ICollection<TValue>, new() 
{ 
    TList list; 
    if (!lookup.TryGetValue(key, out list)) 
    { 
     lookup.Add(key, list = new TList()); 
    } 
    list.Add(value); 
} 

static void Main() { 
    var data = new Dictionary<string, List<string>>(); 
    data.Add("abc", "def"); 
} 
+0

Schön! I <4 Erweiterungsmethoden. –

+0

In der Tat nett, obwohl ich noch nicht wirklich überzeugt bin, wenn es um Wartbarkeit und obskure Sachen geht, die damit gemacht werden können. Zum Beispiel Implementieren von Standardimplementierungen für Schnittstellen mit Erweiterungsmethoden. Aber in diesem Fall sehr praktisch! – Kevin

1

einen Verweis auf System.Data.DataSetExtensions hinzufügen und Sie können die Linq-Erweiterungen verwenden:

var dictOfLst = ds.Tables[0].Rows. 
    //group by the key field 
    GroupBy(dr => dr.Field<string>("key")). 
    ToDictionary(
     grp => grp.Key, 
     //convert the collection of rows into values 
     grp => grp.Select(dr => dr.Field<string>("value")).ToList()); 

ich bin nicht sicher, ob ich mit einer anderen Klasse stören würde, aber ein Dienstprogramm oder Erweiterung Methode, um diese einfacher machen könnte:

public static Dictionary<TKey, List<TValue>> ToGroupedDictionary<TKey, List<TValue>>(
    this DataTable input, 
    Func<TKey, DataRow> keyConverter, 
    Func<TValue, DataRow> valueConverter) 
{ 
    return input.Rows. 
     //group by the key field 
     GroupBy(keyConverter). 
     ToDictionary(
      grp => grp.Key, 
      //convert the collection of rows into values 
      grp => grp.Select(valueConverter).ToList()); 
} 

//now you have a simpler syntax 
var dictOfLst = ds.Tables[0].ToGroupedDictionary(
    dr => dr.Field<string>("key"), 
    dr => dr.Field<string>("value")); 
+1

Haben Sie ToLookup gesehen? –

0

Nicht vergessen the using directive.

Dies ist nicht direkt ansprechbar, kann aber trotzdem hilfreich sein. Ein "using alias" für einen generischen Sammlungstyp kann Ihren Code für die Augen erleichtern.

Credit to SO für diesen Hinweis.

0

Warum vereinfachen nicht nur ein wenig:

foreach (DataRow dr in ds.Tables[0].Rows) 
{ 
    string key = dr["Key"].ToString(); 
    if (!Foo.ContainsKey(key)) Foo.Add(key, new List<string>()); 
    Foo[key].Add(dr["Value"].ToString()); 
} 
+0

Ein Grund, dies nicht zu tun, ist, dass die Komplexität O (2n) anstatt O (n) wäre. In den meisten Fällen ist das wahrscheinlich nicht wirklich ein Problem. – Brann

Verwandte Themen