2009-02-20 17 views
55

Come potrei creare un dizionario a più valori in C#?Dizionario multi valore

E.g. Dictionary<T,T,T> dove il primo T è la chiave e gli altri due sono valori.

quindi questo sarebbe possibile: Dictionary<int,object,double>

Grazie

risposta

57

Basta creare un tipo Pair<TFirst, TSecond> e l'uso che come valore.

Ho un esempio di uno nel mio C# in Depth source code. Riprodotto qui per semplicità:

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

Qual è il vantaggio rispetto a un normale KeyValuePair? C'è qualche tipo di sovraccarico quando si utilizza un KeyValuePair? – tanascius

+1

Principalmente è una differenza di enfasi - mentre KeyValuePair incapsula davvero una coppia di valori, implica un particolare tipo di relazione tra loro ... questo non lo è. –

+13

È uguale a Tuple in .Net 4.0? – adam0101

3

non credo che si può fare direttamente. Puoi creare una classe contenente sia il tuo object e il double e inserirne comunque un'istanza nel dizionario.

class Pair 
{ 
    object obj; 
    double dbl; 
} 

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

Edit: Sorry - ho dimenticato non si ottiene tuple fino NET 4.0 viene fuori. D'oh!

+1

Le tuple sono in .NET 4.0 BCL e non sono correlate a C# 4.0. Le funzionalità di C# 4.0 non menzionano il supporto della tupla. Per favore correggi la tua risposta. –

+0

Il problema con la tupla è che i valori non sono nominati. – ProfK

+1

Inoltre i valori di Tupla sono di sola lettura, il che potrebbe andar bene per alcuni casi, ma dovrebbe essere considerato prima di usarli. –

2

Se i valori sono correlati, perché non incapsularli in una classe e basta usare il semplice vecchio dizionario?

+0

Sarà più leggibile di Pair e Tuple. Qual è il primo, secondo, elemento1, elemento2? – KornMuffin

5

Penso che questo sia piuttosto eccessivo per una semantica del dizionario, poiché il dizionario è per definizione una raccolta di chiavi e i relativi valori, proprio come il modo in cui vediamo un libro di dizionario di una lingua che contiene una parola come chiave e il suo significato descrittivo come valore.

Ma si può rappresentare un dizionario che può contenere insieme di valori, ad esempio:

Dictionary<String,List<Customer>> 

o un dizionario di una chiave e il valore come un dizionario:

Dictionary<Customer,Dictionary<Order,OrderDetail>> 

Poi si' Avremo un dizionario che può avere più valori.

+0

Buona risposta ...! – nawfal

+1

Non appena avvii i dizionari di nesting, il tuo codice inizia ad apparire come array multidimensionali. – IAbstract

+0

@IAbstract non è così simile nella semantica. Gli array multidimensionali non si preoccupano della combinazione di valori-chiave. Anche gli array multidimensionali non si preoccupano dell'elemento massimo di due (proprio come deve avere il dizionario). –

1

Descrivi un multimap.

È possibile rendere il valore un oggetto Elenco, per memorizzare più di un valore (> 2 per l'estensibilità).

Ignora l'oggetto dizionario.

41

Se si sta tentando di raggruppare i valori, questa può essere una grande opportunità per creare una struttura o una classe semplice e utilizzarla come valore in un dizionario.

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

allora si potrebbe avere il dizionario

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

si potrebbe anche fare un passo ulteriore e implementare la propria classe dizionario che consente di gestire tutte le operazioni speciali che si avrebbe bisogno.per esempio se si voleva avere un metodo Add che ha accettato un int, oggetto, e doppio

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

allora si potrebbe semplicemente istanziare e aggiungere al dizionario in questo modo e che non avrebbe dovuto preoccuparsi di creare 'MyValue 'struct:

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

ho risolto utilizzando:

Dictionary<short, string[]> 

Ti piace questa

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