Как использовать метод HashSet‹string›.Contains() в режиме без учета регистра?

Как использовать метод HashSet<string>.Contains() в режиме без учета регистра?


person Tasawer Khan    schedule 19.04.2010    source источник
comment
Один боковой узел: когда создается «обычный» HashSet<string> (с учетом регистра), невозможно создать эффективный метод contains. Это связано с тем, что хэши элементов создаются при их добавлении в файл HashSet. А внутри метод contains проверяет эффективность хэшей. Невозможно (эффективно) преобразовать существующую форму хэша «с учетом регистра» в «без учета регистра».   -  person Julian    schedule 24.03.2011


Ответы (4)


Вы можете создать HashSet с помощью специального компаратора:

HashSet<string> hs = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

hs.Add("Hello");

Console.WriteLine(hs.Contains("HeLLo"));
person João Angelo    schedule 19.04.2010
comment
+1 Потому что вы используете Ordinal вместо InvariantCulture. Рекомендации .NET советуют нам не использовать InvariantCulture в большинстве случаев (см.: msdn. microsoft.com/en-us/library/ms973919.aspx). - person Steven; 19.04.2010
comment
Обычно лучшим выбором является CurrentCultureIgnoreCase. - person Hans Passant; 19.04.2010
comment
mdsdn говорит: используйте StringComparison.Ordinal или OrdinalIgnoreCase для сравнений в качестве безопасного значения по умолчанию для сопоставления строк, не зависящих от культуры. - person Amit; 11.04.2014
comment
Я считаю, что CurrentCultureIgnoreCase не пройдет тест Турции. LIST и list не совпадут, если текущая культура — Турция, поскольку строчной буквой I в этой культуре является не i, а ı без точки. Поэтому, если вы ожидаете, что LIST == list, вы будете разочарованы тем, что если текущая культура - индейка, то это вернет false. Если строки, которые вы сравниваете, не являются строками на языке пользователя, т.е. Если это какие-то строки, не имеющие ничего общего с языком пользователя, используйте InvariantCultureIgnoreCase - person AaronLS; 26.04.2014
comment
Невозможно изменить, но верно то, что OrdinalIgnoreCase обычно предпочтительнее, чем InvariantCultureIgnoreCase. Я просто хотел указать, почему CurrentCultureIgnoreCase, вероятно, неприменим (но зависит от того, относится ли эта строка к языку пользователя или нет). - person AaronLS; 26.04.2014

Вам нужно создать его с правами IEqualityComparer:

HashSet<string> hashset = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
person Kobi    schedule 19.04.2010

Здесь нет необходимости, как показали другие ответы, но в других случаях, когда вы не используете строку, вы можете реализовать IEqualityComparer<T>, а затем использовать перегрузку .Contains. Вот пример использования строки (опять же, другие ответы показали, что уже есть компаратор строк, который вы можете использовать, который соответствует вашим потребностям). Многие методы, окружающие IEnumerable<T>, имеют перегруженные версии, которые принимают такие компараторы, поэтому полезно научиться их реализовывать.

class CustomStringComparer : IEqualityComparer<string>
{
    public bool Equals(string x, string y)
    {
        return x.Equals(y, StringComparison.InvariantCultureIgnoreCase);
    }

    public int GetHashCode(string obj)
    {
        return obj.GetHashCode();
    }
}

А затем использовать его

bool contains = hash.Contains("foo", new CustomStringComparer());
person Anthony Pegram    schedule 19.04.2010

Вам следует использовать конструктор, который позволяет вам указать IEqualityComparer, который вы хотите использовать.

HashSet<String> hashSet = new HashSet<String>(StringComparer.InvariantCultureIgnoreCase);

Объект StringComparer предоставляет некоторые часто используемые компараторы в качестве статических свойств.

person Thibault Falise    schedule 19.04.2010