Использование Hashtables/Dictionaries со строковыми клавишами и нечувствительным к регистру
Интересно, возможно ли это.
У нас есть сторонняя библиотека, которая содержит идентификационную информацию о пользователях...
Основное взаимодействие с библиотекой осуществляется через HashTable, который связан с строкой и возвращает Object Graph информации для этого ключа.
Проблема заключается в том, что ключ, очевидно, чувствителен к регистру, но то, что мы получаем из браузера пользователей, не обязательно соответствует случаю... (Мы часто получаем ключ в нижнем регистре)
Мне интересно, можно ли сделать случай Нечувствительный поиск ключа против хеш-таблицы.
например.
Hashtable ht = new Hashtable();
ht.Add("MyKey", "Details");
string result = ht["MyKey"];
string result = ht["MYKEY"];
string result = ht["mykey"];
В случае непредвиденных обстоятельств мы можем отправить в компанию поддержку для добавления этой функции, есть ли какие-либо другие DataStructures (т.е. новые общие коллекции/словари), которые поддерживают эту функциональность
Наконец, можно ли переопределить метод System.String GetHashCode(), чтобы
сделать все случаи инвариантных строк возвратом одного и того же хэш-кода... например. Я думаю, что это не goer, поскольку string
- запечатанный класс
Приветствия, если у кого есть предложения
Ответы
Ответ 1
Код, чтобы сделать сравнения хэш-таблицы нечувствительными к регистру
Для 2.0, 3.0, 3.5
Hashtable ht = new Hashtable(StringComparer.InvariantCultureIgnoreCase);
Вы можете получить информацию об InvariantCultureIgnoreCase и OrdinalIgnoreCase на этой ссылке SO
ИЛИ
Hashtable ht = System.Collections.Specialized.CollectionsUtil.CreateCaseInsensitiveHashtable();
Так как коллекция данных, не учитывающая регистр, является таким распространенным явлением,.NET Framework имеет класс CollectionUtil, который поддерживает создание объектов Hashtable и SortedList, которые нечувствительны к регистру. Используйте, вызвав CreateCaseInsensitiveHashtable или CreateCaseInsensitiveSortedList.
Для .Net 1.0 (я не уверен, поддерживает ли 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());
Ответ 2
Со словарем:
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
но проще, я считаю, что StringDictionary
тоже не чувствителен к регистру:
StringDictionary ht = new StringDictionary();
ht.Add("MyKey", "Details");
string result1 = ht["MyKey"];
string result2 = ht["MYKEY"];
string result3 = ht["mykey"];
Ответ 3
Вы можете предоставить конструктор IEqualityComparer
без учета регистра IEqualityComparer
, но это требует, чтобы вы могли влиять на конструкцию HashTable
в сторонней библиотеке.
Если вы заполняете хэш-таблицу из своего кода, вы можете нормализовать ключи при вставке и снова получить нормализованные ключи.
Если вы не можете влиять на содержимое хэш-таблицы, но знаете структуру ключей, вы можете исправить ввод пользователя перед доступом к хеш-таблице.
Ответ 4
Это не очень эффективный способ, но вы всегда можете взять хэш-таблицу и сделать из нее 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