【问题标题】:Generating unique id for a given list/set/array of unique numbers为给定的唯一数字列表/集合/数组生成唯一 ID
【发布时间】:2020-04-27 14:49:34
【问题描述】:

我的数组包含从 0 到 integer.max 值的随机唯一数字。

如何生成唯一的 id/signature(int) 来唯一标识每个数组,而不是搜索每个数组并检查每个数字。

例如

int[] x = {2,4,8,1,88,12....};
int[] y = {123,456,64,87,1,12...};
int[] z = {2,4,8,1...};
int[] xx = {213,3534,778,1,2,234....};
..................
..................
and so on.

每个数组可以有不同的长度,但数字在数组内不重复,可以在其他数组中重复。每个数组唯一的 id 的目的是通过 id 来识别它,以便快速搜索。数组包含组件的 ID,数组的唯一签名/ID 将识别其中包含的组件。

此外,无论数组中值的顺序如何,生成的 id 都应该是相同的。像 {1,5} 和 {5,1} 应该生成相同的 id。

我查找了不同的数字配对方法,但结果数字会随着数组的长度增加到无法放入 int 的程度而增长。

分配给组件的 IDS 可以调整,它们不必是整数序列,只要有合适的数字范围即可。唯一的要求是,一旦为数组(组件 id 的集合)生成了 id,它们就不应发生冲突。如果该数组中的集合发生变化,则可以在运行时生成。

【问题讨论】:

  • 贴出你目前尝试过的代码。
  • 你希望这个 id 到底在哪里?如果你想要它在数组中,你可以开始添加负数作为第一个数字(例如,第一个数组有 -1,第二个有 -2 等等)

标签: java encryption cryptography wolfram-mathematica


【解决方案1】:

这可以通过带有顺序归一化函数(例如sort())的散列函数h() 来近似解决。散列函数是有损的,因为唯一散列(2^32 或 2^64)的数量小于可能的可变长度整数集的数量,导致两个不同集具有相同 ID 的可能性很小(散列冲突)。通常,如果

  • 您使用了良好的哈希函数,并且
  • 您的数据集并没有大得离谱。

顺序归一化函数将确保集合 {x, y} 和 {y, x} 被散列到相同的值。

对于散列函数,您有很多选择,但请选择将冲突概率降至最低的散列,例如加密散列(SHA-256、MD5),或者如果您需要前沿性能,请使用 MurmurHash3 或其他常规散列。 MurmurHash3 可以产生一个整数作为输出,而加密哈希需要一个额外的步骤,即从二进制输出中提取 4 或 8 个字节并解包为整数。 (使用任何一致的字节选择,例如第一个或最后一个。)

在伪代码中:

int getId(setOfInts) {
    intList = convert setOfInts to integer list
    sortedIntList = sort(intList)
    ilBytes = cast sortedIntList to byte array
    hashdigest = hash(ilBytes)
    leadingBytes = extract 4 or 8 leading bytes of hashdigest
    idInt = cast leadingBytes to integer
    return idInt
}

【讨论】:

    【解决方案2】:

    严格来说,您要求的内容是不可能的:即使只有两个元素的数组,也有比可能的签名(232)。而且您的数组不限于两个元素,因此您的情况会呈指数级恶化。

    但是,如果您可以接受较低的重复率和错误匹配率,那么一种简单的方法是使用 + 运算符将所有元素相加(它本质上计算模 232支持>)。这是 java.util.Set 的 hashCode() 方法所采用的方法。它并不能完全消除比较整个数组的需要(因为您需要检测错误匹配),但它会从根本上减少此类比较的数量(因为很少有数组会匹配任何给定数组)。

    【讨论】:

      【解决方案3】:

      您希望 {1, 5} 和 {5, 1} 具有相同的 ID。这排除了标准哈希函数,在这种情况下会给出不同的结果。一种选择是在散列之前对数组进行排序。请注意,加密哈希很慢;您可能会发现像 FNV 这样的非加密哈希就足够了。肯定会更快。

      如@ruakh 建议的那样,为了避免排序,只需添加所有数字 mod 2^32 或 mod 2^64,并接受您将有一定比例的冲突。添加数组长度将避免一些冲突:在这种情况下 {5, 1} 将不匹配 {1, 2, 3} 为 (2+(5+1)) != (3+(1+2+3) )。您可能想用您的真实数据进行测试,看看这是否有足够的优势。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-09
        相关资源
        最近更新 更多