1. ホーム
  2. c#

[解決済み】汎用辞書の大文字・小文字を区別しないアクセス方法

2022-03-27 14:20:22

質問

マネージドDLLを使用するアプリケーションを持っています。これらのDLLの1つは、一般的な辞書を返します。

Dictionary<string, int> MyDictionary;  

辞書は大文字と小文字のキーを含む。

別の側面では、私は潜在的なキーのリスト(文字列)を取得していますが、私は大文字と小文字を保証することはできません。 私はキーを使って辞書の中の値を取得しようとしています。しかし、大文字小文字の不一致があるので、当然ながら以下の処理は失敗します。

bool Success = MyDictionary.TryGetValue( MyIndex, out TheValue );  

TryGetValueに期待したのは 無視する場合 で述べたようなフラグを MSDNドキュメント しかし、これは一般的な辞書には有効でないようです。

キーケースを無視して、その辞書の値を取得する方法はありますか? 辞書の新しいコピーを作成し、適切な 文字列比較器.OrdinalIgnoreCase パラメータは?

どのように解決するのですか?

を指定する方法はありません。 StringComparer を、値を取得しようとする地点に置く。考えてみれば "foo".GetHashCode()"FOO".GetHashCode() は全く異なるものなので、大文字小文字を区別しないハッシュマップの取得を実装することは合理的ではありません。

しかし、大文字小文字を区別しない辞書を最初に作成することはできます:-)

var comparer = StringComparer.OrdinalIgnoreCase;
var caseInsensitiveDictionary = new Dictionary<string, int>(comparer);

または、既存の大文字小文字を区別する辞書の内容で、新しい大文字小文字を区別しない辞書を作成する(大文字小文字の衝突がないことが確認されている場合):-。

var oldDictionary = ...;
var comparer = StringComparer.OrdinalIgnoreCase;
var newDictionary = new Dictionary<string, int>(oldDictionary, comparer);

この新しい辞書は、次に GetHashCode() の実装は StringComparer.OrdinalIgnoreCase そこで comparer.GetHashCode("foo")comparer.GetHashcode("FOO") は同じ値を与えます。

また、辞書に含まれる要素が少なく、1、2回しか検索する必要がない場合、元の辞書を IEnumerable<KeyValuePair<TKey, TValue>> で、それを反復するだけです:-)

var myKey = ...;
var myDictionary = ...;
var comparer = StringComparer.OrdinalIgnoreCase;
var value = myDictionary.FirstOrDefault(x => String.Equals(x.Key, myKey, comparer)).Value;

あるいは、LINQを使わない方法もあります。

var myKey = ...;
var myDictionary = ...;
var comparer = StringComparer.OrdinalIgnoreCase;
int? value;
foreach (var element in myDictionary)
{
  if (String.Equals(element.Key, myKey, comparer))
  {
    value = element.Value;
    break;
  }
}

これにより、新しいデータ構造を作成するコストを削減することができますが、その代わり、ルックアップのコストはO(1)ではなくO(n)になります。