私は、キーがタプルである最初の項目が日付で、2番目の項目が文字列である辞書を持っています。私は大文字小文字を区別しないでください。タプルキーで大文字と小文字を区別しない辞書
キーが単なる文字列だった場合、辞書を宣言するときにStringComparer.OrdinalIgnoreCaseをパラメータとして渡すことができますが、キーがタプルのときは機能しないようです。
タプルの2番目の項目で使用するStringComparerを指定する方法はありますか?
おかげ
私は、キーがタプルである最初の項目が日付で、2番目の項目が文字列である辞書を持っています。私は大文字小文字を区別しないでください。タプルキーで大文字と小文字を区別しない辞書
キーが単なる文字列だった場合、辞書を宣言するときにStringComparer.OrdinalIgnoreCaseをパラメータとして渡すことができますが、キーがタプルのときは機能しないようです。
タプルの2番目の項目で使用するStringComparerを指定する方法はありますか?
おかげ
あなたがキーのカスタム比較子を指定することができますDictionary
コンストラクタの使用this overload。あなたはこのようになります
IEqualityComparer<Tuple<string, DateTime>>
を実装するクラスを作成し、これを伴うだろう。ここには、引数のチェックはありません
class CustomEqualityComparer : IEqualityComparer<Tuple<string, DateTime>>
{
public bool Equals(Tuple<string, DateTime> lhs, Tuple<string, DateTime> rhs)
{
return
StringComparer.CurrentCultureIgnoreCase.Equals(lhs.Item1, rhs.Item1)
&& lhs.Item2 == rhs.Item2;
}
public int GetHashCode(Tuple<string, DateTime> tuple)
{
return StringComparer.CurrentCultureIgnoreCase.GetHashCode(tuple.Item1)
^tuple.Item2.GetHashCode();
}
}
ので、本番コードとして扱いしないでください
。また、Equals
と
GetHashCode
の実装が、2つのタプルが等しいと比較される場合は、
の同じ重要な条件を満たし、同じハッシュコードを持つように注意する必要があります。カスタムテキストの比較を扱うときは、細心の注意を払わずにバグを導入するのは簡単です。たとえば、上記の
ToLower
の代わりに
ToLowerInvariant
を使用すると、バグになることがあります。
比較は大文字と小文字を区別しないので、タプルを作成するときにtoLower
/toUpper
メソッドを文字列側で使用して、検索に使用されたタプルの文字列を常に上または下にします/辞書のエントリを比較する。
文字列を大文字または小文字に変換して比較することは、一部の文化では正しく機能しません。 StringComparer.CurrentCultureIgnoreCaseなどのStringComparerを使用する方がよいでしょう。 – dtb
私はDictionary<Tuple<>>
ラッパーでこれを必要なので、私は平等のためにして取得するためにチェックするために、同じStringComparerを使用してジェネリック版
public class TupleEqualityComparer<T1, T2> : IEqualityComparer<Tuple<T1, T2>>
{
private IEqualityComparer<T1> comparer1;
private IEqualityComparer<T2> comparer2;
public TupleEqualityComparer(IEqualityComparer<T1> comparer1, IEqualityComparer<T2> comparer2)
{
this.comparer1 = comparer1 ?? EqualityComparer<T1>.Default;
this.comparer2 = comparer2 ?? EqualityComparer<T2>.Default;
}
public bool Equals(Tuple<T1, T2> lhs, Tuple<T1, T2> rhs)
{
return comparer1.Equals(lhs.Item1, rhs.Item1) && comparer2.Equals(lhs.Item2, rhs.Item2);
}
public int GetHashCode(Tuple<T1, T2> tuple)
{
return comparer1.GetHashCode(tuple.Item1)^comparer2.GetHashCode(tuple.Item2);
}
}
public class Dictionary<TKey1, TKey2, TValue> : Dictionary<Tuple<TKey1, TKey2>, TValue>()
{
public Dictionary() : base() { }
public Dictionary(IEqualityComparer<TKey1> comparer1, IEqualityComparer<TKey2> comparer2) : base(new TupleEqualityComparer<TKey1, Tkey2>(comparer1, comparer2) { }
public TValue this[TKey1 key1, TKey2 key2]
{
get { return base[Tuple.Create(key1, key2)]; }
}
public void Add(TKey1 key1, TKey2 key2, TValue value)
{
base.Add(Tuple.Create(key1, key2), value);
}
public bool ContainsKey(TKey1 key1, TKey2 key2)
{
return base.ContainsKey(Tuple.Create(key1, key2));
}
public bool TryGetValue(TKey1 key1, TKey2 key2, out TValue value)
{
return base.TryGetValue(Tuple.Create(key1, key2), out value);
}
}
使用
var dict = new Dictionary<string, DateTime, int>(
StringComparer.OrdinalIgnoreCase, null);
dict.Add("value1", DateTime.Now, 123);
Assert.IsTrue(dict.ContainsKey("VALUe1"));
を作成するために、@ジョンのコードを使用ハッシュコードは、あなたが言及したバグを避けるのに最も効果的です。私は提案された修正で答えを編集しました。あなたがそれを気に入らなければ元に戻してください。 – dtb
@dtb:これはIMOでも一貫性の向上であるため、間違いなく元に戻すことはありません。ありがとう! – Jon