C#の文字列キータイプを使用した大文字と小文字を区別しない辞書


156

私が持っている場合、大文字と小文字を区別しないDictionary<String,...>ような方法を作ることは可能ContainsKeyですか?

これは関連しているように見えましたが、私はそれを正しく理解していませんでした:c#辞書:宣言によってキーの大文字と小文字を区別しません


6
使用の何が問題になっていStringComparer.InvariantCultureIgnoreCaseますか?それはそれが言うことをします...
leppie

5
聞いたことがないので、質問!
氏Mr. Boy


その質問は関連していますが、この質問の完全な重複ではありません。それは、既存の辞書をどのように扱うかに入ります。私は新しいコードから始めているので、ここでの答えはより適しています。
goodeye

回答:


322

これは関連しているように見えましたが、私はそれを正しく理解していませんでした:c#辞書:宣言によってキーの大文字と小文字を区別しません

それは確かに関連しています。解決策は、辞書インスタンスに標準の文字列比較メソッド(大文字と小文字を区別する)を使用せず、大文字と小文字を区別しない方法を使用するように指示することです。これは適切なコンストラクタを使用して行われます

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

コンストラクタは、IEqualityComparerキーを比較する方法をディクショナリに指示するを期待します。

StringComparer.InvariantCultureIgnoreCaseIEqualityComparer大文字と小文字を区別しない方法で文字列を比較するインスタンスを提供します。


1
パーフェクト、私はどういうわけかSTLのような方法で、コンパレーターを俳優に渡すのに失敗しました。
Boy氏

7
ここでコーディングに関する質問への答えを常に見つける方法に驚かされることは決してありません!多分私はあなたの次の猫、コンラッドに名前を付けます!:-)
ジェイミー

10
可能性のある、より高速な文化をベースに比べStringComparison.OrdinalIgnoreCaseコンペアラー:stackoverflow.com/questions/492799/...
Manushinイゴール

ディクショナリを作成していないが、オブジェクトの一部として取得した既存のディクショナリで大文字と小文字を区別しないキー照合にContainsKey()を使用しようとしている場合、どうすればよいですか?
Shridhar R Kulkarni

1
@ShridharRKulkarni基本的に(効率的に)できません。比較ロジックは、内部辞書データ構造の中核部分です。これを可能にするために、コンテナーはデータの複数のインデックスを維持する必要があり、辞書はこれを行いません。
Konrad Rudolph

21
var myDic = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
myDic.Add("HeLlo", "hi");

if (myDic.ContainsKey("hello"))
    Console.WriteLine(myDic["hello"]);

1
コードスニペットはそれをすべて言います。非常に役立ちます。なぜこの投稿が3分遅れただけの承認された回答と比較してそれほど賛成票が少ないのかわかりません。
RBT

14

サードパーティまたは外部のdllからプルされた辞書を扱う可能性はほとんどありません。linqの使用

YourDictionary.Any(i => i.KeyName.ToLower().Contains("yourstring")))


3
これはうまくいきます。あなたが変更した場合は注意の言葉は、かかわらずAnySingleOrDefault取得することはできません、あなたnullが存在しない場合は、バック、代わりにあなたはへのキーと値のセットの両方を持つkeyvaluepairを取得しますnull
NibblyPig 2017年

1
Contains当時あなたが取り組んでいたものの非常に具体的なユースケースのようです。より一般的な役立つ答えとして、私Equalsはより良いと思います。そして、同じことを言うと、で文字列を複製する代わりに、ToLower()を使用しStringComparison.xxxCaseたほうがよいでしょう。
Suamere

1
これは非常に便利で、ToLowerを取り除くことは間違いなく改善です-私の使用例は次のとおりです。大文字と小文字を区別しない辞書に含まれています。
デビッドバーフォード

私はこれに反対票を投じたいと思っています。注意:あなたが辞書の所有者である場合、これは間違いなくそうする方法ではありません。辞書がどのようにインスタンス化されたかがわからない場合にのみ、このアプローチを使用してください。それでも、文字列を完全に一致させるには(部分一致だけではない)、使いdict.Keys.Contains("bla", appropriate comparer)やすさのためにLINQオーバーロードを使用します。
nawfal

1

ASP.NET CoreコントローラーでcaseINsensitive辞書を必要とするのと同じ種類の問題に遭遇しました。

私はトリックを行う拡張メソッドを書きました。多分これは他の人にも役立つかもしれません...

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!");

0

インスタンスの作成を制御できない場合、たとえばオブジェクトがjsonなどから非滅菌化されている場合は、辞書クラスから継承するラッパークラスを作成できます。

public class CaseInSensitiveDictionary<TValue> : Dictionary<string, TValue>
{
    public CaseInSensitiveDictionary() : base(StringComparer.OrdinalIgnoreCase){}
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.