324

管理されたdllを使用するアプリケーションがあります。それらのdllの1つは、一般的な辞書を返します。

Dictionary<string, int> MyDictionary;  

辞書には大文字と小文字のキーが含まれています。

別の側面では、潜在的なキー(文字列)のリストを取得していますが、ケースを保証することはできません。キーを使用して辞書の値を取得しようとしています。しかしもちろん、ケースの不一致があるため、以下は失敗します。

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

I was hoping the TryGetValue would have an ignore case flag like mentioned in the MSDN doc, but it seems this is not valid for generic dictionaries.

Is there a way to get the value of that dictionary ignoring the key case? Is there a better workaround than creating a new copy of the dictionary with the proper StringComparer.OrdinalIgnoreCase parameter?

4

4 に答える 4

671

StringComparer値を取得しようとする時点でa を指定する方法はありません。考えてみると、"foo".GetHashCode()まったく"FOO".GetHashCode()異なるため、大文字と小文字を区別するハッシュマップで大文字と小文字を区別しない get を実装する合理的な方法はありません。

ただし、最初に次を使用して大文字と小文字を区別しない辞書を作成できます。

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) になります。

于 2012-11-05T10:44:26.450 に答える