我正在尝试在0和非常低的n之间散列一些字符串,以便为每个用户提供一种颜色。
这是我的(工作)代码:
function nameToColor(name) {
var colors = ['red', 'blue', 'green', 'purple', 'orange', 'darkred', 'darkblue', 'darkgreen', 'cadetblue', 'darkpurple'];
var hash = hashStr(name);
var index = hash % colors.length;
return colors[index];
}
//djb2 hash
function hashStr(str) {
var hash = 5381;
for (var i = 0; i < str.length; i++) {
var charCode = str.charCodeAt(i);
hash = ((hash << 5) + hash) + charCode; /* hash * 33 + c */
}
return hash;
}
不幸的是,低数字被大量过多。
问题:
如何编写一个确定性的javascript函数,它将任何字符串作为参数并返回一个好的(尽可能统一)分布,数字介于0和n之间?
答案 0 :(得分:7)
Hogan在javascript中给了几个哈希实现评论link。事实证明,最简单的是最合适的:
function nameToColor(name) {
var colors = ['red', 'blue', 'green', 'purple', 'orange', 'darkred', 'darkblue', 'darkgreen', 'cadetblue', 'darkpurple'];
var hash = hashStr(name);
var index = hash % colors.length;
return colors[index];
}
//very simple hash
function hashStr(str) {
var hash = 0;
for (var i = 0; i < str.length; i++) {
var charCode = str.charCodeAt(i);
hash += charCode;
}
return hash;
}
我认为它运作良好,因为它只使用与模运算符交换的加法(无移位或乘法),因此保持了初始分布质量。
我还在维基百科上找到了this,但没有必要使用它:
在许多应用程序中,散列值的范围对于程序的每次运行可能是不同的,或者可能沿着相同的运行而改变(例如,当需要扩展散列表时)。在这些情况下,需要一个哈希函数,它接受两个参数 - 输入数据z和允许哈希值的数量n。
一个常见的解决方案是用非常计算一个固定的哈希函数 大范围(例如,0到232 - 1),将结果除以n,并使用 师的剩余部分。如果n本身是2的幂,则可以通过以下方式完成 位屏蔽和位移。使用此方法时,哈希 必须选择函数以使结果相当均匀 在0和n - 1之间的分布,对于可能出现的任何n值 应用程序。根据功能,其余部分可能是 仅对n的某些值均匀,例如奇数或素数。
我们可以允许表格大小n不是2的幂,但仍然不是 必须执行任何剩余或除法操作,因为这些 计算有时是昂贵的。例如,让n显着 少于2b。考虑一个伪随机数发生器(PRNG) 函数P(key)在区间[0,2b-1]上是均匀的。哈希 区间[0,n-1]上的函数均匀是n P(密钥)/ 2b。我们可以 通过(可能更快的)右位移来代替除法:nP(键)&gt;&gt;湾
答案 1 :(得分:1)
Brian White的以下哈希函数非常通用,使用任何类型的输入(包括字符串),附带简单示例,并为Javascript node.js编写。
https://npmjs.org/package/xxhash
希望这有帮助