2009-02-16 16 views
18

Powiel możliwe:
C# Sortable collection which allows duplicate keysCzy istnieje alternatywa dla Dictionary/SortedList, która umożliwia duplikaty?

Zasadniczo chciałbym zrobić słownik pracę z duplikatów kluczy bez wchodzenia implementacji niestandardowych comparer. Istnieje pomysł:

Dictionary<key, List<value>> 

, ale nadal ma pewne obciążenie. Chciałbym mieć słownik "AllowDuplicates".

+0

Nie znaleziono tego w moich wyszukiwaniach. Zagłosowano na blisko, dzięki. –

+0

Również powiązane: http: // stackoverflow.com/questions/5716423/c-sharp-sortable-collection-which-lets-duplicate-keys –

Odpowiedz

13

Jeśli używasz .NET 3.5, to prawdopodobnie jest to, czego oczekujesz od Lookup.

+4

Szkoda, że ​​taka potencjalnie przydatna klasa ma kilka ograniczeń. Takich jak żaden publiczny konstruktor ani możliwość dodawania/usuwania elementów. – Ray

+2

@Ray, Zgadzam się całkowicie. Chociaż myślę, że to dlatego nazywa się Lookup, a nie coś takiego jak MultiDictionary, aby wskazać, że jest to niezmienne spojrzenie, a nie kolekcja do manipulowania. Propozycja OP Słownika > byłaby znacznie bardziej elastyczna. – LukeH

+0

@Ray: najlepszy konstruktor jest, cytuję MSDN: „Można utworzyć instancję Lookup wywołując ToLookup na obiekt, który implementuje IEnumerable .” –

3

Nie w Fx < 3.5 .. Można go oczywiście zaimplementować za pomocą Słownika obiektów IList. Ale wtedy masz problem enkapsulacji/odpowiedzialności.

Jeśli używasz .NET 3.5, użyj klasy Lookup.

+0

To tylko zamiennik dla 'Dictionary', ale nie dla' SortedList'. –

0

Z definicji słownik zawiera unikatowe klucze. Twój powyższy przykład jest właściwie rodzajem dwuwymiarowej tabliczki z kluczami, strukturą, której używałam wiele razy. Dlaczego chcesz mieć zduplikowane klucze? Gdyby tak było, w jaki sposób słownik unikalnie adresowałby swoich członków?

+5

Rozważmy słownik świata zawierający różne znaczenia tego samego słowa. Wiele wpisów za pomocą wspólnego klucza. Nic w tym sprzecznego. Członkowie mogą być adresowani przez odnośnik zwracający kolekcję lub Enumerable. C++ ma wielowątkowy od wieków. To nie jest problem niemożliwy. :) – jalf

1

natknąłem z samym numerze .. Potrzebowałem SortedList który może umożliwić podwójne klucze ..

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

ale to nie działał .. więc użyłem

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

dodać nowe dane do to jak ..

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

z LINQ i posortowane go bez problemu ..

Spróbuj List<KeyValuePair<TKey, List<TValue>>>();

+4

nie należy zapominać, że to nie ma O (N) koszt wyszukiwania według klucza w przeciwieństwie do hashtable (lub słownika), który jest w większości przypadków O (1). –

4

nadal można używać SortedList i starać się unikatowy klucz łącząc swoją wartość i Guid do klasy. W tym przypadku należy wdrożyć IComparer<NewKey> dla nowego klucza, coś takiego:

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

a następnie

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

To nie działa. Jak tylko zwrócisz 0 z porównywarki, wyrzuci "duplikat" wyjątku.

Nie potrzebujesz hermetyzacji klas ani niczego, po prostu utworzymy porównywarkę, która nie zwróci wyniku 0 (równego). Oto przykład dla klucza int

class MyComparer : IComparer<int> 
{ 

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

Należy pamiętać, że ta sztuczka złamie indeks. Jeśli spróbujesz uzyskać wartość za pomocą indeksera, otrzymasz wyjątek, ponieważ klucza nie można znaleźć. –