Подтвердить что ты не робот

Использование 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 - запечатанный класс

Приветствия, если у кого есть предложения

4b9b3361

Ответ 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