2009-05-13 18 views
17

Preguntándose si esto es posible.Uso de Hashtables/Diccionarios con teclas de secuencia y Búsqueda sin distinción de mayúsculas y minúsculas

Tenemos una biblioteca tercera Parte que contiene información de identificación acerca de los usuarios ...

La principal interacción con la biblioteca es a través de una tabla hash que está adaptada con una cadena, y devuelve un gráfico de objetos de información para esa clave .

El problema es, la clave es, obviamente, mayúsculas y minúsculas, pero lo que obtenemos de los usuarios del navegador no necesariamente coinciden con el caso ... (a menudo conseguir la llave completamente lowercase'd)

I' Me pregunto si es posible hacer un caso Búsqueda de clave insensible en una tabla hash.

p. Ej.

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

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

En la remota posibilidad de que pudiéramos enviar un ticket de soporte a la empresa para agregar esta funcionalidad, ¿existen otras estructuras de datos (es decir, las nuevas colecciones genéricas/diccionarios) que soportan esta funcionalidad

Por último, sería es posible anular el método System.String GetHashCode(), a hacer que todas las cadenas invariantes de casos devuelvan el mismo código hash ... por ejemplo Estoy pensando que esto es un no aficionado al string como es una clase cerrada

Saludos, si alguien tiene alguna sugerencia

+4

aparte: si está utilizando .NET 3.5, probablemente debería dejar de usar Hashtable, etc., y comenzar a utilizar las colecciones genéricas en su lugar. –

+0

Re su comentario: tal vez simplemente llame a .ToLowerInvariant() en todas sus claves, entonces. –

+0

* scratch head * Pero las claves que están dentro de la Hashtable no son ToLowered(). Es decir. Me dieron una tabla hash pre construida que está instanciada/poblada dentro de un dll. y las teclas en HT son sensibles a mayúsculas/minúsculas ... El único acceso que tengo al dll es a través de un getter/indexer donde paso la clave, así que incluso si toLowerInvarianted mis claves en el exterior, no coincidirían con las claves en el interior. –

Respuesta

30

código para hacer las comparaciones entre mayúsculas y minúsculas tabla hash

durante 2,0, 3,0, 3,5

Hashtable ht = new Hashtable(StringComparer.InvariantCultureIgnoreCase); 

, usted puede obtener información sobre InvariantCultureIgnoreCase vs OrdinalIgnoreCase en this SO enlace

O

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

Porque case-insensi La colección de diccionarios tive es un uso tan común, .NET Framework tiene una clase CollectionUtil que admite la creación de objetos Hashtable y SortedList que no distinguen entre mayúsculas y minúsculas. Use llamando a CreateCaseInsensitiveHashtable o CreateCaseInsensitiveSortedList.

Para .Net 1.0 (no estoy seguro de si es compatible con 1.0 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 clase StringComparer ya proporciona comparadores sin distinción de mayúsculas y minúsculas, sin necesidad de implementar la suya propia. –

+0

Gracias Daniel. He editado mi respuesta. –

+0

Esto es solo un FYI: descubrí que las claves StringDictionary no distinguen entre mayúsculas y minúsculas por defecto. Pero tanto la clave como el valor deben ser cadenas. –

17

Con un diccionario:

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

pero más simple, creo StringDictionary entre mayúsculas y minúsculas demasiado:

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

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

Cheers Marc. Y aplaude a los demás por señalar las sobrecargas de IEqualityOperator ... Desafortunadamente, no tengo acceso a las partes internas de la biblioteca ni a la construcción de la Hashtable ... Solo descubrí la implementación mediante el uso de Reflector para introducir en su interior . Creo que registraré un ticket de soporte con la empresa y les preguntaré si se puede agregar como una "Característica" –

2

puede suministrar una IEqualityComparer a la HashTable constructor entre mayúsculas y minúsculas, pero esto requiere que pueda influir en la construcción HashTable en la biblioteca de terceros.

Si completa la tabla hash desde su código, puede normalizar las teclas al insertar y recuperar las claves normalizadas nuevamente.

Si no puede influir en el contenido de la tabla hash, pero conoce la estructura de las teclas, puede corregir la entrada del usuario antes de acceder a la tabla hash.

1

Esto no es una forma muy eficiente, pero siempre se puede tomar la tabla hash y hacer una StringDictionary de ella:

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 Esta es una buena idea. (Pero falla en "FOO" y "foo" en la tabla hash). –

+0

Bueno, usar el indexador en lugar del método Add evitaría una excepción, y ninguna solución tendría el mismo problema, si el Hashtable original tiene múltiples claves que difieren solo por caso? – Rytmis

Cuestiones relacionadas