案例不敏感词典与元组键

时间:2013-05-07 21:02:53

标签: c# dictionary string-comparison

我有一个字典,其中键是元组,其中第一项是日期,第二项是字符串。我希望字典不区分大小写。

我知道如果键只是一个字符串,我可以在声明字典时将StringComparer.OrdinalIgnoreCase作为参数传递,但是当键是元组时,这似乎不起作用。

是否有某种方法可以指定要在元组的第二项上使用的StringComparer?

由于

3 个答案:

答案 0 :(得分:19)

使用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();
    }
}

此处没有参数检查,因此请不要将其视为生产代码。此外,需要注意使EqualsGetHashCode实现满足的最重要条件,如果两个元组比较相等,它们必须具有相同的哈希码。在处理自定义文本比较时,如果不是特别小心,很容易引入错误:例如,使用ToLowerInvariant代替上面的ToLower将是一个错误(虽然可能在一段时间内没有浮出水面)。

答案 1 :(得分:3)

我在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"));

答案 2 :(得分:1)

由于比较将不区分大小写,因此在制作元组时可以在字符串方面使用toLower / toUpper方法,然后始终降低或提高字符串的大小。在元组中有用于检索/比较字典中的条目。