我想到了两件事作为解决方案的基础:
求和不依赖于顺序,这实际上是简单校验和的缺陷(它们无法捕获单词内块顺序的更改),
我们可以使用字符编码将字符串转换为可相加的数字
下面是一个执行(2)的函数:
charsum = function(s) {
var i, sum = 0;
for (i = 0; i < s.length; i++) {
sum += (s.charCodeAt(i) * (i+1));
}
return sum
}
这里是计算数组哈希的(1)版本,它通过对charsum值求和来计算:
array_hash = function(a) {
var i, sum = 0
for (i = 0; i < a.length; i++) {
var cs = charsum(a[i])
sum = sum + (65027 / cs)
}
return ("" + sum).slice(0,16)
}
代码演示: http://jsfiddle.net/WS9dC/11/
如果我们直接对 charsum 值求和,则数组 ["a", "d"] 会与数组 ["b", "c"] 具有相同的哈希值,导致不良冲突。因此,基于使用非 UTF 字符串,其中 charcodes 最高可达 255,并允许每个字符串中有 255 个字符,则 charsum 的最大返回值为 255 * 255 = 65025。因此,我选择了下一个素数 65027,并使用 (65027 / cs) 计算哈希。我并不百分之百地确信这会消除冲突...也许需要更多思考...但它肯定修复了 [a, d] 对 [b, c] 的情况。
测试:
var arr1 = ['alpha','beta','gama'];
var arr2 = ['beta','alpha','gama'];
console.log(array_hash(arr1))
console.log(array_hash(arr2))
console.log(array_hash(arr1) == array_hash(arr2))
输出:
443.5322979371356
443.5322979371356
true
测试一个展示不同哈希值的案例:
var arr3 = ['a', 'd'];
var arr4 = ['b', 'c'];
console.log(array_hash(arr3))
console.log(array_hash(arr4))
console.log(array_hash(arr3) == array_hash(arr4))
输出:
1320.651443298969
1320.3792001649144
false
编辑:
以下是修订版,它在进行处理时会忽略数组中的重复项,并且只基于唯一项目返回哈希值:
http://jsfiddle.net/WS9dC/7/
array_hash = function(a) {
var i, sum = 0, product = 1
for (i = 0; i < a.length; i++) {
var cs = charsum(a[i])
if (product % cs > 0) {
product = product * cs
sum = sum + (65027 / cs)
}
}
return ("" + sum).slice(0, 16)
}
测试:
var arr1 = ['alpha', 'beta', 'gama', 'delta', 'theta', 'alpha', 'gama'];
var arr2 = ["beta", "gama", "alpha", "theta", "delta", "beta"];
console.log(array_hash(arr1))
console.log(array_hash(arr2))
console.log(array_hash(arr1) === array_hash(arr2))
返回结果:
689.878503111701
689.878503111701
true
编辑
我已经修改了上面的答案,以考虑具有相同字母的单词数组。我们需要这些返回不同的哈希值,现在它们已经做到了:
var arr1 = ['alpha', 'beta']
var arr2 = ['alhpa', 'ateb']
修复方法是基于字符索引向charsum函数添加乘数:
sum += (s.charCodeAt(i) * (i+1));
JSON.stringify
可能是一个选项,比join
更好,但我仍然需要进行排序。我怀疑那是无法避免的。 - FredyCarr.join("\0")
,似乎没有人会在字符串中放置空字符... - Bart|
作为分隔符,这两个数组将产生相同的哈希值:["abc", "def|ghi"]
和["abc","def","ghi"]
。 - Barmar