2009-02-16 26 views
18

Eventuali duplicati:
C# Sortable collection which allows duplicate keysEsiste un'alternativa a Dictionary/SortedList che consente duplicati?

Fondamentalmente mi piacerebbe fare un lavoro di dizionario con chiavi duplicate senza entrare in implementazioni Comparer personalizzato. C'è un'idea di:

Dictionary<key, List<value>> 

ma ha ancora un sovraccarico. Vorrei che Dizionario avesse "AllowDuplicates".

+0

Non ho trovato questo nelle mie ricerche. Votato per vicino, grazie. –

+0

Relativi anche: http: // stackoverflow.it/questions/5716423/c-sharp-sortable-collection-which-allows-duplicate-keys –

risposta

13

Se si utilizza .NET 3.5 quindi Lookup è probabilmente quello che stai cercando.

+4

È un peccato che una classe potenzialmente utile abbia alcune limitazioni. Come nessun costruttore pubblico o possibilità di aggiungere/rimuovere elementi. – Ray

+2

@Ray, accetta completamente. Anche se immagino sia per questo che si chiama Lookup piuttosto che qualcosa come MultiDictionary, per suggerire che si tratta di una ricerca immutabile di qualche tipo piuttosto che di una collezione da manipolare. Il suggerimento dell'OP di un dizionario > sarebbe molto più flessibile. – LukeH

+0

@Ray: Il miglior costruttore è, e cito MSDN: "È possibile creare un'istanza di una ricerca chiamando ToLookup su un oggetto che implementa IEnumerable . " –

3

Non in Fx < 3.5 .. È possibile implementarne uno, ovviamente, con un dizionario di oggetti IList. Ma poi hai il problema/la responsabilità dell'incapsulamento.

Se si utilizza .NET 3.5, utilizzare la classe Lookup.

+0

È solo un sostituto di 'Dictionary', ma non di' SortedList'. –

0

Per definizione, un dizionario contiene chiavi univoche. Il tuo esempio sopra è effettivamente una sorta di array con chiave bidimensionale, una struttura che ho usato molte volte. Perché vorresti avere chiavi duplicate? Se lo facessi, come potrebbe il dizionario indirizzare in modo univoco i suoi membri?

+5

Considera un dizionario del mondo reale che elenca significati diversi per la stessa parola. Più voci con una chiave comune. Niente di contraddittorio. I membri possono essere indirizzati da una ricerca che restituisce una raccolta o Enumerable. Il C++ ha avuto una multimap per secoli. Non è un problema impossibile. :) – jalf

1

mi sono imbattuto con stesso problema .. Ho bisogno di un SortedList che può permettere chiavi duplicate ..

var sortList = new SortedList<string, IDictionary<string, object>>(); 

ma questo lavoro non ha ancora .. così ho usato

var list = new List<KeyValuePair<string, IDictionary<string, object>>>(); 

di aggiungere nuovi dati come ..

list.Add(new KeyValuePair<string, IDictionary<string, object>>>(value, Dictionary)); 

con LINQ ho risolto senza alcun problema ..

0.123.

Prova List<KeyValuePair<TKey, List<TValue>>>();

+4

Non dimenticare che questo ha O (N) ricerca per chiave a differenza di un hashtable (o un dizionario), che è O (1) principalmente. –

4

È comunque possibile utilizzare SortedList e cercare di fare una chiave unica, combinando il vostro valore e un GUID in una classe. In questo caso, è necessario implementare il IComparer<NewKey> per la nuova chiave, qualcosa di simile:

class MyKey 
{ 
    public Guid Guid { get; set; } 
    public float Value { get; set; } 
} 

class MyComparer : IComparer<MyKey> 
{ 

    public int Compare(MyKey x, MyKey y) 
    { 
     if (x == null || y == null) 
      throw new InvalidOperationException("both of parameters must be not null"); 
     if (x.Value < y.Value) return -1; 
     if (x.Value > y.Value) return 1; 
     return 0; 
    } 
} 

e poi

var mySortedList = new SortedList<MyKey, MyValue>(new MyComparer()); 
2

che non funziona. Non appena si restituisce 0 dal comparatore, verrà generata un'eccezione "duplicata".

Non è necessario l'incapsulamento delle classi o altro, basta creare un confronto che non restituisca il risultato 0 (uguale). Ecco un esempio per il tipo di chiave int

class MyComparer : IComparer<int> 
{ 

    public int Compare(int x, int y) 
    { 
    if (x < y) 
     return -1; 
    else return 1; 
    } 
} 
+3

Ricorda che questo trucco spezzerà l'indicizzatore. Se si tenta di ottenere un valore utilizzando l'indicizzatore, si otterrà un'eccezione perché la chiave non è stata trovata. –