2009-05-13 18 views
17

Zastanawiasz się, czy jest to możliwe.Używanie zeszytów/słowników z kluczami ciągów i rozróżnianie wielkości liter w wyszukiwaniu

Mamy bibliotekę 3rd Party, który zawiera informacje identyfikujące o użytkownikach ...

Głównym interakcja z biblioteki jest przez HashTable która jest zaklinowana z ciągiem, i zwraca Graph Object informacji dla tego klucza .

Problem polega na tym, kluczem jest oczywiście wielkość liter, ale to, co otrzymujemy od użytkowników przeglądarki niekoniecznie pasuje sprawę ... (Często dostać klucz pełni lowercase'd)

I Zastanawiam się, czy da się zrobić przypadek Nieczułe wyszukiwanie klucza przed hashtable.

np.

Hashtable ht = new Hashtable(); 
ht.Add("MyKey", "Details"); 

string result = ht["MyKey"]; 
string result = ht["MYKEY"]; 
string result = ht["mykey"]; 

Na off szansa moglibyśmy przesłać zgłoszenie do pomocy technicznej do firmy, aby dodać tę funkcjonalność, czy są jakieś inne datastructures (czyli nowe kolekcje generyczne/słowników), które obsługują tę funkcjonalność

Wreszcie będzie możliwe jest przesłonięcie metody System.String GetHashCode() na , dzięki czemu wszystkie ciągi niezmienników przypadku zwracają ten sam kod skrótu ... np. Myślę, że to jest bez nawiązań jako string jest szczelna klasa

Cheers jeśli ktoś ma jakieś sugestie

+4

jako na bok: jeśli korzystasz z .NET 3.5 prawdopodobnie powinieneś przestać używać Hashtable itp. - i zacznij używać ogólnych kolekcji. –

+0

Powtórz swój komentarz: może po prostu zadzwoń .ToLowerInvariant() na wszystkie twoje klucze, wtedy. –

+0

* głowa drapania * Ale klawisze znajdujące się w Hashtable nie są ToLowered(). To znaczy. Dostaję pre-built hashtable, który jest instancjonowany/zapełniony wewnątrz dll. a klawisze w HT są rozróżniane na wielkości liter ... Jedyny dostęp do biblioteki dll jest przez program pobierający/indeksujący, gdzie przekazuję klucz, więc nawet jeślibym użył Nieważne, moje klucze na zewnątrz, nie pasowałyby do kluczy W środku. –

Odpowiedz

30

kod aby hashtable dokonanie porównania wielkości liter

przez 2,0, 3,0, 3,5

Hashtable ht = new Hashtable(StringComparer.InvariantCultureIgnoreCase); 

można uzyskać informacje na InvariantCultureIgnoreCase vs. OrdinalIgnoreCase na this SO linku

LUB

Hashtable ht = System.Collections.Specialized.CollectionsUtil.CreateCaseInsensitiveHashtable(); 

Ponieważ case-insensi kolekcja słownika tive jest tak powszechnym użytkiem, .NET Framework ma klasę CollectionUtil, która obsługuje tworzenie obiektów Hashtable i SortedList, które nie są rozróżniane wielkości liter. Użyj, wywołując CreateCaseInsensitiveHashtable lub CreateCaseInsensitiveSortedList.

dla .NET 1.0 (nie jestem pewien, czy 1.0 obsługuje StringComparer)

public class InsensitiveComparer : IEqualityComparer 
{ 
    CaseInsensitiveComparer _comparer = new CaseInsensitiveComparer(); 
    public int GetHashCode(object obj) 
    { 
     return obj.ToString().ToLowerInvariant().GetHashCode(); 
    } 

    public new bool Equals(object x, object y) 
    { 
     if (_comparer.Compare(x, y) == 0) 
     { 
      return true; 
     } 

     else 
     { 
      return false; 
     } 
    } 
} 

Hashtable dehash = new Hashtable(new InsensitiveComparer()); 
+1

Klasa StringComparer już zapewnia porównywanie wielkości liter - nie ma potrzeby implementacji własnej. –

+0

Dzięki Daniel. Zmieniłem moją odpowiedź. –

+0

To jest tylko FYI: dowiedziałem się, że klucze StringDictionary są domyślnie niewrażliwe na wielkość liter. Ale zarówno klucz, jak i wartość muszą być ciągami. –

17

ze słownikiem:

new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); 

ale prostsze, wierzę StringDictionary jest wielkość liter też:

StringDictionary ht = new StringDictionary(); 
    ht.Add("MyKey", "Details"); 

    string result1 = ht["MyKey"]; 
    string result2 = ht["MYKEY"]; 
    string result3 = ht["mykey"]; 
+0

Pozdrawiam Marc. I wiwaty dla innych za wskazanie przeciążenia IEqualityOperator ... Niestety, nie mam dostępu do wewnętrznych elementów biblioteki ani do konstrukcji HashTable ... Odkryłem tylko implementację za pomocą Reflectora, aby wsunąć dookoła niego . Myślę, że zapiszę zgłoszenie do pomocy technicznej w firmie i zapytam, czy można go dodać jako "Cecha". –

2

można dostarczyć IEqualityComparer do HashTable konstruktora bez uwzględniania wielkości liter, ale wymaga to wpływu na konstrukcję HashTable w bibliotece trzeciej.

Jeśli wypełnisz tabelę mieszania za pomocą kodu, możesz normalizować ponownie klawisze wstawiania i odzyskiwania znormalizowanych klawiszy.

Jeśli nie możesz wpłynąć na zawartość tabeli hash, ale znasz strukturę kluczy, możesz poprawić dane wprowadzane przez użytkownika przed uzyskaniem dostępu do tabeli mieszającej.

1

Nie jest to bardzo skuteczny sposób, ale zawsze można wziąć hashtable i zrobić z niego StringDictionary:

Hashtable ht = new Hashtable(); 
ht.Add("FOO", "bar"); 

StringDictionary dict = new StringDictionary(); 

foreach(string key in ht.Keys) 
    dict.Add(key, ht[key].ToString()); 

string result = dict["foo"]; // Assigns "bar" to result 
+1

+1 To jest miły pomysł. (Ale kończy się niepowodzeniem w przypadku "FOO" i "foo" w tabeli mieszania). –

+0

No cóż, użycie indeksera zamiast metody Add zapobiegnie wyjątkowi, a żadne rozwiązanie nie będzie miało tego samego problemu, jeśli oryginalny Hashtable ma wiele klucze różnią się tylko wielkością liter? – Rytmis