几个Linq.Enumerable函数都有一个IEqualityComparer<T>
。有没有一个方便的包装类来适应实现IEqualityComparer<T>
的delegate(T,T)=>bool
?编写一个很容易(如果您忽略了定义正确的哈希码的问题),但是我想知道是否有开箱即用的解决方案。
具体地说,我希望在Dictionary
上执行集合操作,只使用键来定义成员身份(同时根据不同的规则保留值)。
发布于 2010-09-16 00:13:50
通常,我会通过在答案上评论@Sam来解决这个问题(我已经对原始帖子进行了一些编辑,以便在不改变行为的情况下对其进行一些清理。)
以下是我的@Sam's answer摘要,以及对默认散列策略的IMNSHO关键修复:
class FuncEqualityComparer<T> : IEqualityComparer<T>
{
readonly Func<T, T, bool> _comparer;
readonly Func<T, int> _hash;
public FuncEqualityComparer( Func<T, T, bool> comparer )
: this( comparer, t => 0 ) // NB Cannot assume anything about how e.g., t.GetHashCode() interacts with the comparer's behavior
{
}
public FuncEqualityComparer( Func<T, T, bool> comparer, Func<T, int> hash )
{
_comparer = comparer;
_hash = hash;
}
public bool Equals( T x, T y )
{
return _comparer( x, y );
}
public int GetHashCode( T obj )
{
return _hash( obj );
}
}
发布于 2009-08-06 14:41:24
当您想要自定义相等检查时,99%的时间您感兴趣的是定义要进行比较的键,而不是比较本身。
这可能是一个优雅的解决方案(来自Python的list sort method的概念)。
用法:
var foo = new List<string> { "abc", "de", "DE" };
// case-insensitive distinct
var distinct = foo.Distinct(new KeyEqualityComparer<string>( x => x.ToLower() ) );
KeyEqualityComparer
类:
public class KeyEqualityComparer<T> : IEqualityComparer<T>
{
private readonly Func<T, object> keyExtractor;
public KeyEqualityComparer(Func<T,object> keyExtractor)
{
this.keyExtractor = keyExtractor;
}
public bool Equals(T x, T y)
{
return this.keyExtractor(x).Equals(this.keyExtractor(y));
}
public int GetHashCode(T obj)
{
return this.keyExtractor(obj).GetHashCode();
}
}
发布于 2008-09-18 23:52:01
恐怕没有开箱即用的包装器。然而,创建一个并不难:
class Comparer<T>: IEqualityComparer<T>
{
private readonly Func<T, T, bool> _comparer;
public Comparer(Func<T, T, bool> comparer)
{
if (comparer == null)
throw new ArgumentNullException("comparer");
_comparer = comparer;
}
public bool Equals(T x, T y)
{
return _comparer(x, y);
}
public int GetHashCode(T obj)
{
return obj.ToString().ToLower().GetHashCode();
}
}
...
Func<int, int, bool> f = (x, y) => x == y;
var comparer = new Comparer<int>(f);
Console.WriteLine(comparer.Equals(1, 1));
Console.WriteLine(comparer.Equals(1, 2));
https://stackoverflow.com/questions/98033
复制相似问题