Czy są jakieś klasy słownikowe w bibliotece klas podstawowych .NET, które pozwalają na użycie zduplikowanych kluczy? Jedyne rozwiązanie, jakie znalazłem, to na przykład utworzenie klasy takiej jak:
Dictionary<string, List<object>>
Ale to irytujące w użyciu. Uważam, że w Javie MultiMap to osiąga, ale nie może znaleźć analogu w .NET.
c#
.net
dictionary
multimap
Ślimak mechaniczny
źródło
źródło
{ a, 1 }
oraz{ a, 2 }
w tabeli mieszania, gdziea
jest klucz, jedna alternatywa jest mieć{ a, [1, 2] }
.Odpowiedzi:
Jeśli używasz .NET 3.5, użyj
Lookup
klasy.EDYCJA: Na ogół tworzysz za
Lookup
pomocąEnumerable.ToLookup
. Zakłada się, że nie musisz go później zmieniać - ale zazwyczaj uważam, że to wystarczy.Jeśli to nie zadziała, nie sądzę, aby w ramach było coś, co by pomogło - a używanie słownika jest tak dobre, jak to możliwe :(
źródło
Lookup
nie można serializowaćKlasa List faktycznie działa całkiem dobrze w przypadku kolekcji kluczy / wartości zawierających duplikaty, w których chciałbyś wykonać iterację po kolekcji. Przykład:
źródło
Oto jeden ze sposobów, aby to zrobić za pomocą List <KeyValuePair <string, string>>
Wyjścia k1 = v1, k1 = v2, k1 = v3
źródło
Jeśli używasz ciągów jako kluczy i wartości, możesz użyć System.Collections.Specialized.NameValueCollection , który zwróci tablicę wartości ciągu za pomocą metody GetValues (klucz ciągu).
źródło
Właśnie natrafiłem na bibliotekę PowerCollections, która zawiera między innymi klasę o nazwie MultiDictionary. To starannie otacza ten rodzaj funkcjonalności.
źródło
Bardzo ważna uwaga dotycząca korzystania z odnośnika:
Możesz utworzyć instancję
Lookup(TKey, TElement)
wywołaniaToLookup
obiektu, który implementujeIEnumerable(T)
Nie ma publicznego konstruktora, aby utworzyć nową instancję pliku
Lookup(TKey, TElement)
. PonadtoLookup(TKey, TElement)
obiekty są niezmienne, to znaczy nie można dodawać ani usuwać elementów ani kluczy zLookup(TKey, TElement)
obiektu po jego utworzeniu.(z MSDN)
Sądzę, że dla większości zastosowań byłby to ogranicznik pokazu.
źródło
Wydaje mi się, że coś podobnego
List<KeyValuePair<object, object>>
wykona zadanie.źródło
Jeśli używasz> = .NET 4, możesz użyć
Tuple
klasy:źródło
List<KeyValuePair<key, value>>
powyższe rozwiązanie. Czy się mylę?Łatwo jest „rzucić własną” wersję słownika, która pozwala na „zduplikowanie klucza”. Oto z grubsza prosta implementacja. Możesz rozważyć dodanie obsługi praktycznie większości (jeśli nie wszystkich) włączonych
IDictionary<T>
.Szybki przykład jak go używać:
źródło
W odpowiedzi na oryginalne pytanie. Coś takiego
Dictionary<string, List<object>>
jest zaimplementowane w klasie o nazwieMultiMap
TheCode Project
.Możesz znaleźć więcej informacji na poniższy link: http://www.codeproject.com/KB/cs/MultiKeyDictionary.aspx
źródło
NameValueCollection obsługuje wiele wartości ciągu pod jednym kluczem (który jest również ciągiem), ale jest to jedyny przykład, jaki znam.
Mam tendencję do tworzenia konstrukcji podobnych do tego w twoim przykładzie, kiedy napotykam sytuacje, w których potrzebuję tego rodzaju funkcjonalności.
źródło
Korzystając z tej
List<KeyValuePair<string, object>>
opcji, możesz użyć LINQ, aby przeprowadzić wyszukiwanie:źródło
Ponieważ nowy C # (wierzę, że pochodzi z wersji 7.0), możesz również zrobić coś takiego:
i używasz go jako standardowej listy, ale z dwiema wartościami o dowolnej nazwie
źródło
Masz na myśli przystającą, a nie faktyczną kopię? W przeciwnym razie tablica mieszająca nie byłaby w stanie działać.
Congruent oznacza, że dwa oddzielne klucze mogą mieszać do równoważnej wartości, ale klucze nie są równe.
Na przykład: powiedzmy, że funkcja skrótu twojego hashtable była po prostu hashval = klucz mod 3. Zarówno 1, jak i 4 są odwzorowane na 1, ale są różnymi wartościami. Tutaj zaczyna się pomysł na twoją listę.
Gdy musisz wyszukać 1, ta wartość jest haszowana na 1, lista jest przesuwana do momentu znalezienia Key = 1.
Jeśli zezwolisz na wstawianie duplikatów kluczy, nie będziesz w stanie rozróżnić, które klucze odwzorowują na które wartości.
źródło
Sposób, w jaki korzystam, jest po prostu
Dictionary<string, List<string>>
W ten sposób masz jeden klucz z listą ciągów.
Przykład:
źródło
Natknąłem się na ten post w poszukiwaniu tej samej odpowiedzi, ale nie znalazłem żadnej, więc przygotowałem przykładowe rozwiązanie od podstaw, używając listy słowników, zastępując operatora [], aby dodać nowy słownik do listy, gdy wszystkie inne mają dany klucz (zestaw) i zwraca listę wartości (get).
Jest brzydka i nieefektywna, pobiera / ustawia TYLKO według klucza i zawsze zwraca listę, ale działa:
źródło
Zmieniłem odpowiedź @Hector Correa na rozszerzenie o typach ogólnych, a także dodałem do niej niestandardową TryGetValue.
źródło
To jest jednoczesny słownik. Myślę, że to pomoże ci:
przykłady:
źródło
korzystam z tej prostej klasy:
stosowanie:
źródło
Możesz stworzyć własne opakowanie słownika, coś takiego jak ten, jako bonus obsługuje wartość zerową jako klucz:
Próbka użycia:
źródło
var dictionary = new OpenDictionary<string, int>(); dictionary.Add("1", 1); // The next line won't throw an exception; dictionary.Add("1", 2); dictionary.TryGetEntries("1", out List<int> result); // result is { 1, 2 }
Możesz zdefiniować metodę budowania klucza ciągów złożonych w każdym miejscu, w którym chcesz używać słownika. Musisz użyć tej metody do zbudowania klucza, na przykład:
za korzystanie:
źródło
Duplikaty kluczy psują cały kontrakt Słownika. W słowniku każdy klucz jest unikalny i przypisany do jednej wartości. Jeśli chcesz powiązać obiekt z dowolną liczbą dodatkowych obiektów, najlepszym rozwiązaniem może być coś podobnego do zestawu danych (w języku potocznym tabela). Umieść klucze w jednej kolumnie, a wartości w drugiej. Jest to znacznie wolniejsze niż słownik, ale to twój kompromis za utratę możliwości mieszania kluczowych obiektów.
źródło
Jest to również możliwe:
W ten sposób możemy mieć unikalne klucze. Mam nadzieję, że to Ci odpowiada.
źródło
Możesz dodać te same klucze w różnych przypadkach, takich jak:
klucz1
Key1
KEY1
klucz1
klucz1
klucz1
Wiem, że to fałszywa odpowiedź, ale dla mnie zadziałało.
źródło