使用.Equals()而不是散列的C#Dictionary

时间:2012-01-23 03:43:56

标签: c# dictionary

是否存在类似于Dictionary的数据结构,允许基于为给定类而不是散列值定义的.Equals()调用添加唯一元素。

在我的例子中,我有一个PointD类定义一个带有十进制X和Y的点。由于十进制类型的性质有点不精确,因此在点上创建一个哈希是不可能的,因为两点之间的一个小错误基本相同的将导致哈希值的主要差异。

基本上,我希望能够计算每个x,y组合的点数。是否有现成的机制,或者我是否需要自己实现?

5 个答案:

答案 0 :(得分:4)

小心点。听起来你想要定义Equals,以便在一定容差范围内的值被认为是相等的。如果你这样做,Equals将不会传递,但它需要传递以使字典起作用。

示例:假设x小于y的公差的0.8倍。他们被认为是平等的。现在考虑值z,它比y大0.8倍。因此y和z也相等。但是x和z 相等!

GetHashCode必须为两个相等的对象返回相同的值。由于此系统中的相等性不可传递,因此您可以证明GetHashCode需要为所有对象返回相同的值,这会导致您的字典像链接列表一样(但具有更多的存储开销,浪费)。

您可以通过将所有点四舍五入到一定程度的精度来解决这个问题,并从舍入值计算哈希码和相等性。当然,这种方法可能有其自身的缺陷。

答案 1 :(得分:1)

是的,您可以创建自己的IEqualityComparer并在构造它时将其传递给字典....它不使用Equal,但您可以使它自己做哈希。

如果你想在实际的Point类上保留Hash,这会更好一些。

答案 2 :(得分:0)

只需覆盖PointD类的GetHashCode方法以满足您的需求,不是吗?

答案 3 :(得分:0)

您不能拥有不使用散列的字典。字典需要哈希函数和相等比较器。哈希码用于获取哈希表中的桶,相等比较器用于检查桶中的值。最重要的要求是,比较相等的值也必须具有相同的哈希码。

在您的情况下我会做的是将点标准化为仅使用一定数量的数字。您可以使用Math.Round方法执行此操作。这样,您可以保留has / equality组合的所有必要属性。

您可以在构造函数中或在EqualsGetHashCode方法(您仍需要)的覆盖中进行舍入。在构造函数中执行此操作的优点是,您只执行一次计算,同时仍然在所有地方强制执行该需求。如果您的类是可变的,那么您还必须在属性设置器中以及直接修改字段的任何位置执行此操作。

答案 4 :(得分:0)

如果您有大量积分,最好的办法是使用类似Dictionary<Point, List<PointD>>的内容,将每个PointD转换为Point。如果X值是公差范围内的值可以舍入到不同的值,则在Dictionary中存储向上舍入和向下舍入的版本。在寻找一个点时,如果Y值是公差范围内的值可以舍入到不同的值,那么在表中查找两者。

请注意,Dictionary操作可能返回List<PointD>的一个或两个实例(仅在Y舍入不明确的情况下有两个实例;这些列表中的部分或全部PointD个实例可能可能与实际兴趣点不匹配,但需要检查的实例数应该是Dictionary中总数的一小部分。

相关问题