Использование Hashtables / Словари со строковыми ключами и поиск без учета регистра - PullRequest
17 голосов
/ 13 мая 2009

Интересно, если это возможно.

У нас есть сторонняя библиотека, которая содержит идентификационную информацию о пользователях ...

Основное взаимодействие с библиотекой происходит через HashTable, который имеет строку и возвращает граф объектов для этого ключа.

Проблема в том, что ключ, очевидно, чувствителен к регистру, но то, что мы получаем из браузера пользователя, не обязательно соответствует регистру ... (Мы часто получаем ключ полностью в нижнем регистре)

Мне интересно, можно ли выполнить регистронезависимый поиск ключа по хеш-таблице.

, например

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

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

Если у нас есть возможность отправить заявку в службу поддержки, чтобы добавить эту функцию, есть ли другие DataStructures (т.е. новые общие коллекции / словари), поддерживающие эту функцию

Наконец, возможно ли переопределить метод System.String GetHashCode (), чтобы сделать все строки, инвариантные к регистру, возвращать один и тот же хэш-код ... например Я думаю, что это не ходят, поскольку string это запечатанный класс

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

Ответы [ 4 ]

31 голосов
/ 13 мая 2009

Код для сравнения хеш-таблиц без учета регистра

Для 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());
17 голосов
/ 13 мая 2009

со словарем:

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"];
2 голосов
/ 13 мая 2009

Можно указать регистр IEqualityComparer без учета регистра для конструктора HashTable, но для этого необходимо, чтобы вы могли влиять на конструкцию HashTable в сторонней библиотеке.

Если вы заполните хеш-таблицу из своего кода, вы можете нормализовать ключи при вставке и снова получить нормализованные ключи.

Если вы не можете повлиять на содержимое хеш-таблицы, но знаете структуру клавиш, вы можете исправить ввод пользователя перед доступом к хеш-таблице.

1 голос
/ 13 мая 2009

Это не очень эффективный способ, но вы всегда можете взять хеш-таблицу и создать из нее 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
...