【发布时间】:2021-08-20 18:04:13
【问题描述】:
我正在处理现有数据并且有包含数组 double[23] 和 double[46] 的记录。数组中的值可以在多条记录中相同。我想生成一个 id(可能是一个 int)来唯一标识每个数组中的值。
应用程序中有些地方我需要根据数组中相同的值对记录进行分组。虽然有很多方法可以查询这个,但我希望有一个单一的 int 字段(或类似的东西)来分组。这确实有助于简化查询,尤其是有助于使用报告工具,在较小的单个字段上进行分组会大有帮助。
我想生成一个哈希码,但我知道对于每个具有匹配值的 double[],这些代码不保证相同。我曾尝试实施
((IStructuralEquatable)combined).GetHashCode(EqualityComparer<double>.Default);
比较结构和数据,但我不认为这是保证匹配另一个具有相同值的 double[]。
也许某种形式的校验和会起作用,但我承认我在实现某些东西时遇到了麻烦。我正在寻找建议/方向。
这是 3 个样本记录的数据。记录 1 和 3 中的数据相同,因此生成的 id 应该与这些数据匹配。 32.7,48.9,55.9,48.9,47.7,46.9,45.7,44.4,43.4,41.9,40.4,38.4,36.7,34.4,32.4,30.4,27.9,25.4,22.4,19.4,16.4,13.4,10.4,47.9 40.8,49.0,50.0,49.0,47.8,47.0,45.8,44.5,43.5,42.0,40.5,38.5,36.8,34.5,32.5,30.5,28.0,25.5,22.5,19.5,16.5,13.5,10.5,48.0 32.7,48.9,55.9,48.9,47.7,46.9,45.7,44.4,43.4,41.9,40.4,38.4,36.7,34.4,32.4,30.4,27.9,25.4,22.4,19.4,16.4,13.4,10.4,47.9
如果不检查所有数据,这可能是不可能的,但希望有更好的解决方案来简化应用程序并提高速度。
目标是在现有记录中添加一个新的 id 字段来表示数组数据。这样一来,将记录传递到报告工具中就可以轻松地在一个字段上组合在一起,而不是检查每条记录上的整个数组。
我很欣赏任何方向。
编辑 - 我在尝试时遇到的一些问题(以防它帮助某人)
在最初试图理解这一点时,我调用了这段代码(它是 .NET 的一部分)。我知道这些函数会将数组的 值 散列在一起(在这种情况下只有 8 个值)。我不认为它包括数组句柄。结果并不像预期的那样,因为根据下面的注释行在 .NET 中纠正了一个错误 MS。通过修复,我得到了更好的结果。
int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) {
if (comparer == null)
throw new ArgumentNullException("comparer");
Contract.EndContractBlock();
int ret = 0;
for (int i = (this.Length >= 8 ? this.Length - 8 : 0); i < this.Length; i++) {
ret = CombineHashCodes(ret, comparer.GetHashCode(GetValue(i)));
//.NET 4.6.2, in .NET 4.5.2 it is ret = CombineHashCodes(ret, comparer.GetHashCode(GetValue(0)))
}
return ret;
}
internal static int CombineHashCodes(int h1, int h2) {
return (((h1 << 5) + h1) ^ h2);
}
我对其进行了修改以处理超过 8 个值,但仍然有一些不匹配的哈希值。后来我确定问题出在数据中;我不知道有些记录有一些双精度数超过一位小数(应该四舍五入)。这当然改变了哈希。现在我的数据是一致的,我看到了匹配的哈希值;任何具有相同值的数组都有相同的哈希值。
【问题讨论】:
-
哈希码可能是您可以使用单个值获得的最接近的值,但有可能发生冲突。为了 100% 的确定性,您需要循环并比较每个值。
-
可能想了解更多关于 C#
GetHashCode的信息,它并不是真正的加密哈希,更便于检查是否有不同。请参阅 stackoverflow.com/a/7425150/1462295 和注意Two unequal objects are not guaranteed to have unequal hashcodes,这更关注单个 32 位哈希值。 -
@Alejandro 我希望有另一种方法,但据我了解,gethashcode 总是有可能发生冲突,因此即使数据相同,某些数组 id 也可能不匹配。我认为 IStructuralEquatable 代码可能会比较数组结构和数据,但似乎仍然有可能发生冲突,因此 id 可能不会一直唯一地表示数据。感谢您的意见。
-
@BurnsBA 感谢 BurnsBA。我在学习过程中学到了一些知识,并且了解可能会发生碰撞。我希望有另一种算法来识别数组,但看起来不太有希望。我没有绑定到 int,只是在寻找比比较每个记录的整个数组更好的东西,但不确定我会摆脱它。也许加密哈希可能没有冲突,但我必须阅读它,因为我还没有使用它的经验。
-
比较 double[23] 中可能的值组合的数量与 int 的可能值的数量,你会发现这是行不通的。