我有一个字典,其中键是元组,其中第一项是日期,第二项是字符串。我希望字典不区分大小写。
我知道如果键只是一个字符串,我可以在声明字典时将 StringComparer.OrdinalIgnoreCase 作为参数传递,但是当键是元组时这似乎不起作用。
有没有办法指定 StringComparer 用于元组的第二项?
谢谢
我有一个字典,其中键是元组,其中第一项是日期,第二项是字符串。我希望字典不区分大小写。
我知道如果键只是一个字符串,我可以在声明字典时将 StringComparer.OrdinalIgnoreCase 作为参数传递,但是当键是元组时这似乎不起作用。
有没有办法指定 StringComparer 用于元组的第二项?
谢谢
使用此构造函数的重载,Dictionary
它允许您为键指定自定义比较器。您将伴随着创建一个实现的类
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
andGetHashCode
实现满足最重要的条件,即如果两个元组比较相等,则它们必须具有相同的哈希码。在处理自定义文本比较时,如果不格外小心,很容易引入错误:例如,使用ToLowerInvariant
而不是ToLower
上面将是一个错误(尽管可能有一段时间不会出现)。
我需要在Dictionary<Tuple<>>
包装器中使用它,所以我使用 @Jon 的代码创建了一个通用版本
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"));
由于比较将不区分大小写,因此您可以在创建元组时在字符串端使用toLower
/方法,然后始终降低或提高用于检索/比较字典中条目的元组中的字符串toUpper
.