Словарь без учета регистра со строковым ключом в C #

Если у меня Dictionary<String,...>, можно ли сделать такие методы, как ContainsKey, нечувствительными к регистру?

Это казалось связанным, но я не понял этого должным образом: Словарь c #: создание ключа без учета регистра через объявления


person Mr. Boy    schedule 21.12.2012    source источник
comment
Возможный дубликат доступа без учета регистра для универсального словаря   -  person Michael Freidgeim    schedule 12.05.2016
comment
Этот вопрос связан, но не повторяет этот. Это касается того, как работать с существующим словарем. Я начинаю с нового кода, поэтому ответы здесь лучше подходят.   -  person goodeye    schedule 27.02.2019


Ответы (4)


Это казалось связанным, но я не понял этого должным образом: c # Dictionary: создание ключа без учета регистра через объявления

Это действительно связано. Решение состоит в том, чтобы указать экземпляру словаря не использовать стандартный метод сравнения строк (который чувствителен к регистру), а использовать метод без учета регистра. Это делается с помощью соответствующего конструктора:

var dict = new Dictionary<string, YourClass>(
        StringComparer.InvariantCultureIgnoreCase);

Конструктор ожидает IEqualityComparer, который сообщает словарь, как сравнивать ключи.

StringComparer.InvariantCultureIgnoreCase предоставляет вам экземпляр IEqualityComparer, который сравнивает строки в без учета регистра.

person Konrad Rudolph    schedule 21.12.2012
comment
Возможно, компаратор StringComparison.OrdinalIgnoreCase быстрее, чем на основе языка и региональных параметров: stackoverflow.com/questions/492799/ - person Manushin Igor; 30.03.2015
comment
Как мне это сделать, если я не создаю словарь, а пытаюсь использовать ContainsKey () для сопоставления ключей без учета регистра в существующем словаре, который я получаю как часть объекта? - person Shridhar R Kulkarni; 22.06.2018
comment
@ShridharRKulkarni Вы принципиально не можете (эффективно). Логика сравнения - это основная часть внутренней структуры данных словаря. Для этого контейнер должен поддерживать несколько индексов для своих данных, а словари этого не делают. - person Konrad Rudolph; 22.06.2018

Есть несколько шансов, что вы имеете дело со словарем, взятым из сторонней или внешней dll. Использование linq

YourDictionary.Any(i => i.KeyName.ToLower().Contains("yourstring")))
person Kurkula    schedule 17.11.2016
comment
Это прекрасно работает. Однако небольшое предостережение: если вы измените Any на SingleOrDefault, вы не получите null обратно, если он не существует, вместо этого вы получите пару ключей и значений, для которых установлено значение null! - person NibblyPig; 02.03.2017
comment
Contains Похоже, это очень специфический вариант использования того, над чем вы работали в то время. В качестве более общего полезного ответа я думаю, что Equals лучше. И в том же примечании, вместо того, чтобы дублировать строку с ToLower(), было бы даже лучше использовать StringComparison.xxxCase. - person Suamere; 06.02.2018
comment
Мне так хочется проголосовать против этого. Предупреждение: если вы владелец словаря, это, безусловно, не способ сделать это. Используйте этот подход, только если вы не знаете, как был создан экземпляр словаря. Даже в этом случае для точного совпадения строки (а не только совпадения частей) используйте перегрузку dict.Keys.Contains("bla", appropriate comparer) LINQ для простоты использования. - person nawfal; 23.07.2019

Если у вас нет контроля над созданием экземпляра, допустим, ваш объект удален из json и т. Д., Вы можете создать класс-оболочку, который наследуется от класса словаря.

public class CaseInSensitiveDictionary<TValue> : Dictionary<string, TValue>
{
    public CaseInSensitiveDictionary() : base(StringComparer.OrdinalIgnoreCase){}
}
person A.G.    schedule 14.07.2020
comment
Как это сделать, сохранив синтаксис Dictionary ‹T1, T2›? - person Ebram Shehata; 07.12.2020

Я столкнулся с той же проблемой, когда мне нужен был чувствительный к регистру словарь в контроллере ASP.NET Core.

Я написал метод расширения, который помогает. Может быть, это будет полезно и для других ...

public static IDictionary<string, TValue> ConvertToCaseInSensitive<TValue>(this IDictionary<string, TValue> dictionary)
{
    var resultDictionary = new Dictionary<string, TValue>(StringComparer.InvariantCultureIgnoreCase);
    foreach (var (key, value) in dictionary)
    {
        resultDictionary.Add(key, value);
    }

    dictionary = resultDictionary;
    return dictionary;
}

Чтобы использовать метод расширения:

myDictionary.ConvertToCaseInSensitive();

Затем получите значение из словаря с помощью:

myDictionary.ContainsKey("TheKeyWhichIsNotCaseSensitiveAnymore!");
person Ferry Jongmans    schedule 22.10.2019