2009-05-13 8 views
17

Chiedersi se è possibile.Utilizzo di hash/Dizionari con tasti stringa e ricerca senza distinzione tra maiuscole e minuscole

Abbiamo una libreria di terze parti che contiene le informazioni di identificazione sugli utenti ...

L'interazione principale con la biblioteca è attraverso un HashTable che viene digitato con una stringa, e restituisce un oggetto grafico di informazioni per quella chiave .

Il problema è che la chiave è ovviamente il caso sensibile, ma ciò che si ottiene dal browser degli utenti non corrisponde necessariamente il caso ... (Spesso ottenere la chiave completamente lowercase'd)

I' Mi chiedo se sia possibile fare un caso. Ricerca di una chiave insensibile contro un hashtable.

ad es.

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

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

Sulla remota possibilità che potremmo inviare una richiesta di assistenza alla società di aggiungere questa funzionalità, vi siano eventuali altre strutture di dati (vale a dire le nuove collezioni generici/dizionari) che supportano questa funzionalità

Infine, sarebbe è possibile sovrascrivere il metodo System.String GetHashCode(), su fare in modo che tutte le stringhe di invarianza del caso restituiscano lo stesso codice hash ... ad esempio Sto pensando che questo è un no frequentatore come string è una classe sealed

Acclamazioni se qualcuno ha qualche suggerimento

+4

come una parte: se si utilizza .NET 3.5 probabilmente si dovrebbe smettere di usare Hashtable ecc. E iniziare invece a utilizzare le raccolte generiche. –

+0

Per il tuo commento: forse basta chiamare .ToLowerInvariant() su tutte le tue chiavi, quindi. –

+0

* graffia testa * Ma i tasti che si trovano nella Hashtable non sono ToLowered(). Cioè Mi viene data una tabella hash pre-compilata che viene istanziata/popolata in una DLL. e le chiavi in ​​HT sono case-sensitive ... L'unico accesso che ho alla dll è tramite un getter/indexer in cui ho passato la chiave, quindi anche se ho toLowerInvarianted le mie chiavi all'esterno, esse non corrisponderebbero alle chiavi all'interno. –

risposta

30

codice per fare i confronti Hashtable

Per 2.0, 3.0 case-insensitive, 3,5

Hashtable ht = new Hashtable(StringComparer.InvariantCultureIgnoreCase); 

è possibile ottenere informazioni InvariantCultureIgnoreCase vs OrdinalIgnoreCase sul this SO collegamento

O

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

Perché case insensi la raccolta di dizionari tive è un uso così comune, .NET Framework ha una classe CollectionUtil che supporta la creazione di oggetti Hashtable e SortedList senza distinzione tra maiuscole e minuscole. Utilizzare chiamando CreateCaseInsensitiveHashtable o CreateCaseInsensitiveSortedList.

for .NET 1.0 (non sono sicuro se 1.0 supporta 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

La classe StringComparer fornisce già comparatori insensibili alle maiuscole e minuscole - non è necessario implementare la propria. –

+0

Grazie Daniel. Ho modificato la mia risposta. –

+0

Questa è solo una FYI: ho scoperto che le chiavi StringDictionary non fanno distinzione tra maiuscole e minuscole per impostazione predefinita. Ma sia la chiave che il valore devono essere stringhe. –

17

con un dizionario:

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

ma più semplice, credo StringDictionary è case-insensitive troppo:

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

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

Cheers Marc. E applausi agli altri per sottolineare i sovraccarichi di IEqualityOperator ... Sfortunatamente, non ho accesso agli interni della libreria o alla costruzione di Hashtable ... Ho scoperto l'implementazione solo utilizzando Reflector per attirare all'interno di esso lo . Penso che registrerò un ticket di supporto con l'azienda e chiederò se può essere aggiunto come "Funzionalità" –

2

È possibile fornire una IEqualityComparer al HashTable costruttore di case-insensitive, ma ciò richiede che tu possa influenzare la costruzione di HashTable nella libreria di terze parti.

Se si riempie la tabella hash dal codice, è possibile normalizzare i tasti al momento dell'inserimento e recuperare nuovamente i tasti normalizzati.

Se non si è in grado di influenzare il contenuto della tabella hash, ma si conosce la struttura dei tasti, è possibile correggere l'input dell'utente prima di accedere alla tabella hash.

1

Questo non è un modo molto efficiente, ma si può sempre prendere la tabella hash e fare uno StringDictionary da esso:

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 Questa è una bella idea. (Ma fallisce su "FOO" e "foo" nella tabella hash.) –

+0

Bene, l'uso dell'indicizzatore invece del metodo Add impedirebbe un'eccezione e nessuna soluzione avrebbe lo stesso problema, se l'Hashtable originale ha più chiavi che differiscono solo per caso? – Rytmis