2009-02-20 17 views
55

Jak utworzyć słownik wielowartościowy w języku C#?Słownik wielowartościowy

E.g. Dictionary<T,T,T> gdzie pierwszy T jest kluczem, a pozostałe dwa to wartości.

więc byłoby to możliwe: Dictionary<int,object,double>

Dzięki

Odpowiedz

57

Po prostu utwórz typ Pair<TFirst, TSecond> i użyj go jako swojej wartości.

Mam przykład jednego w moim C# in Depth source code. Powielana tutaj dla uproszczenia:

using System; 
using System.Collections.Generic; 

public sealed class Pair<TFirst, TSecond> 
    : IEquatable<Pair<TFirst, TSecond>> 
{ 
    private readonly TFirst first; 
    private readonly TSecond second; 

    public Pair(TFirst first, TSecond second) 
    { 
     this.first = first; 
     this.second = second; 
    } 

    public TFirst First 
    { 
     get { return first; } 
    } 

    public TSecond Second 
    { 
     get { return second; } 
    } 

    public bool Equals(Pair<TFirst, TSecond> other) 
    { 
     if (other == null) 
     { 
      return false; 
     } 
     return EqualityComparer<TFirst>.Default.Equals(this.First, other.First) && 
       EqualityComparer<TSecond>.Default.Equals(this.Second, other.Second); 
    } 

    public override bool Equals(object o) 
    { 
     return Equals(o as Pair<TFirst, TSecond>); 
    } 

    public override int GetHashCode() 
    { 
     return EqualityComparer<TFirst>.Default.GetHashCode(first) * 37 + 
       EqualityComparer<TSecond>.Default.GetHashCode(second); 
    } 
} 
+2

Jaka jest przewaga nad normalną KeyValuePair? Czy istnieje jakiś koszt podczas korzystania z KeyValuePair? – tanascius

+1

Głównie jest to różnica w nacisku - podczas gdy KeyValuePair rzeczywiście hermetyzuje parę wartości, implikuje szczególny rodzaj relacji między nimi ... to nie jest możliwe. –

+13

Czy to samo, co Tuple w .Net 4.0? – adam0101

3

I nie sądzę, że można to zrobić bezpośrednio. Można utworzyć klasę zawierającą zarówno twoje object, jak i double i umieścić jej przykład w słowniku.

class Pair 
{ 
    object obj; 
    double dbl; 
} 

Dictionary<int, Pair> = new Dictionary<int, Pair>(); 
19
Dictionary<T1, Tuple<T2, T3>> 

Edit: Niestety - Zapomniałem, że nie dostają krotek aż .NET 4.0 wychodzi. D'oh!

+1

Krotki są w .NET 4.0 BCL i nie są powiązane z C# 4.0. Funkcje C# 4.0 nie wspominają o obsłudze krotek. Popraw odpowiedź. –

+0

Problem z krotką polega na tym, że wartości nie są nazywane. – ProfK

+1

Ponadto wartości Tuple są tylko do odczytu, co może być ok w niektórych przypadkach, ale należy je rozważyć przed ich użyciem. –

2

Jeśli wartości są powiązane, dlaczego nie zamknąć ich w klasie i po prostu użyć zwykłego starego słownika?

+0

Będzie bardziej czytelny niż para i krotka. Co to jest First, Second, Item1, Item2? – KornMuffin

5

Myślę, że jest to przesada w przypadku semantyki słownikowej, ponieważ słownik jest z definicji zbiorem kluczy i odpowiadających im wartości, podobnie jak widzimy książkę ze słownikiem, która zawiera słowo jako klucz i jego opisowe znaczenie jako wartość.

Ale można reprezentować słownika, który może zawierać zbiór wartości, na przykład:

Dictionary<String,List<Customer>> 

lub słownika klucz i wartość jako słownika:

Dictionary<Customer,Dictionary<Order,OrderDetail>> 

Wtedy” Mam słownik, który może mieć wiele wartości.

+0

Dobra odpowiedź ...! – nawfal

+1

Zaraz po uruchomieniu słowników zagnieżdżających kod zaczyna wyglądać jak wielowymiarowe tablice. – IAbstract

+0

@Abstract to nie jest podobne w semantykę. Wielowymiarowe macierze nie dbają o kombinację par klucz-wartość. Również tablice wielowymiarowe nie dbają o maksymalny element dwóch (tak jak musi mieć słownik). –

1

Opisujesz multimap.

Możesz uczynić wartość obiektem List, aby przechowywać więcej niż jedną wartość (> 2 dla rozszerzalności).

Zastępuje obiekt słownika.

41

Jeśli próbujesz grupować wartości razem, może to być świetną okazją do utworzenia prostej struktury lub klasy i użycia jej jako wartości w słowniku.

public struct MyValue 
{ 
    public object Value1; 
    public double Value2; 
} 

wtedy można mieć słownika

var dict = new Dictionary<int, MyValue>(); 

można nawet pójść o krok dalej i realizować własne klasy słownika, który będzie obsługiwać żadnych specjalnych zabiegów, które potrzebujesz.Na przykład, jeśli chcesz mieć dodatek metodę przyjętą int, obiekt, a następnie dwukrotnie

public class MyDictionary : Dictionary<int, MyValue> 
{ 
    public void Add(int key, object value1, double value2) 
    { 
     MyValue val; 
     val.Value1 = value1; 
     val.Value2 = value2; 
     this.Add(key, val); 
    } 
} 

następnie można po prostu utworzyć wystąpienia i dodać do słownika, tak jak i nie będzie musiał martwić się o stworzenie „MyValue 'kodowanym:

var dict = new MyDictionary(); 
dict.Add(1, new Object(), 2.22); 
1

ja rozwiązać za pomocą:

Dictionary<short, string[]> 

Jak to

Dictionary<short, string[]> result = new Dictionary<short, string[]>(); 
result.Add(1, 
      new string[] 
        { 
        "FirstString", 
        "Second" 
        } 
       ); 
     } 
return result;