使用相等比较器的分组算法(我认为所有 LINQ 方法)总是首先比较哈希码,然后只执行Equals
如果两个哈希码相等。您可以看到,如果在相等比较器中添加跟踪语句:
class PointComparer : IEqualityComparer<Point>
{
public bool Equals(Point a, Point b)
{
Console.WriteLine("Equals: point {0} - point {1}", a, b);
return Math.Abs(a.X - b.X) < 1.0;
}
public int GetHashCode(Point point)
{
Console.WriteLine("HashCode: {0}", point);
return point.X.GetHashCode()
^ point.Y.GetHashCode();
}
}
结果是:
HashCode: (1.1, 0)
HashCode: (4.1, 0)
HashCode: (1.2, 0)
HashCode: (4.1, 0)
Equals: point (4.1, 0) - point (4.1, 0)
(1.1, 0),
(4.1, 0), (4.1, 0),
(1.2, 0),
仅针对哈希码相等的两个点Equals
被处决。
现在你可以通过总是返回来欺骗比较0
作为哈希码。如果这样做,输出将是:
HashCode: (1.1, 0)
HashCode: (4.1, 0)
Equals: point (1.1, 0) - point (4.1, 0)
HashCode: (1.2, 0)
Equals: point (4.1, 0) - point (1.2, 0)
Equals: point (1.1, 0) - point (1.2, 0)
HashCode: (4.1, 0)
Equals: point (4.1, 0) - point (4.1, 0)
(1.1, 0), (1.2, 0),
(4.1, 0), (4.1, 0),
现在对于每一对Equals
被执行了,你就得到了你的分组。
But...
什么是“平等”?如果再加一点(2.1, 0.0)
,您想要一组中的哪些点?使用符号≈
对于模糊等式,我们有 -
1.1 ≈ 1.2
1.2 ≈ 2.1
but
1.1 !≈ 2.1
这意味着1.1
and 2.1
永远不会在一个群体中(他们的Equals
永远不会过去)这取决于点的顺序无论1.1
or 2.1
被分组为1.2
.
所以你现在正处于滑坡状态。按邻近度对点进行聚类绝非易事。你正在进入的领域聚类分析 https://en.wikipedia.org/wiki/Cluster_analysis.