首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在Javascript中从字符串生成哈希

在Javascript中从字符串生成哈希
EN

Stack Overflow用户
提问于 2011-10-01 05:52:05
回答 20查看 805.4K关注 0票数 762

我需要将字符串转换为某种形式的散列。这在JavaScript中是可能的吗?

我没有使用服务器端语言,所以我不能那样做。

EN

回答 20

Stack Overflow用户

回答已采纳

发布于 2011-10-01 05:55:20

代码语言:javascript
复制
String.prototype.hashCode = function() {
  var hash = 0, i, chr;
  if (this.length === 0) return hash;
  for (i = 0; i < this.length; i++) {
    chr   = this.charCodeAt(i);
    hash  = ((hash << 5) - hash) + chr;
    hash |= 0; // Convert to 32bit integer
  }
  return hash;
};

来源:http://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/

票数 932
EN

Stack Overflow用户

发布于 2013-03-30 04:09:19

编辑

根据我的jsperf测试,公认的答案实际上更快:

http://jsperf.com/hashcodelordvlad

原创

如果任何人感兴趣,这里有一个改进的(更快的)版本,它将在缺乏reduce数组函数。

代码语言:javascript
复制
hashCode = function(s){
  return s.split("").reduce(function(a,b){a=((a<<5)-a)+b.charCodeAt(0);return a&a},0);              
}

单行箭头函数版本:

代码语言:javascript
复制
hashCode = s => s.split('').reduce((a,b)=>{a=((a<<5)-a)+b.charCodeAt(0);return a&a},0)
票数 178
EN

Stack Overflow用户

发布于 2014-03-16 05:01:53

注意:即使使用最好的32位哈希、冲突意志迟早会发生。

散列冲突概率可以计算为

,近似为

(请看这里)。这可能比直觉所暗示的要高:

假设使用32位散列和k=10,000项,则发生冲突的概率为1.2%。对于77,163个样本,概率变为50%!

(计算器)。

我建议在底部采取一种变通方法。

在回答这个问题时哪种散列算法在唯一性和速度方面最好?,Ian Boyd发布了一个很好的深入分析。简而言之(根据我的解释),他得出的结论是Murmur是最好的,其次是FNV-1a。esmiralha提出的Java的String.hashCode()算法似乎是DJB2的一种变体。

  • FNV-1a的分布比DJB2好,但速度较慢。
  • DJB2比FNV-1a更快,但往往会产生更多的冲突
  • MurmurHash3比DJB2和FNV-1a更好、更快(但优化的实现需要比FNV和DJB2更多的代码行)

下面是一些包含大型输入字符串的基准测试:http://jsperf.com/32-bit-hash何时短相对于DJ2B和FNV-1a,输入字符串被散列,murmur的性能下降:

http://jsperf.com/32-bit-hash/3

因此,总的来说,我会推荐murmur3。

有关JavaScript实现,请参阅此处:

https://github.com/garycourt/murmurhash-js

如果输入字符串很短,并且性能比分发质量更重要,则使用DJB2 (由esmiralha提出的公认答案)。

如果质量和小代码比速度更重要,我使用FNV-1a的这个实现(基于

这段代码)。

代码语言:javascript
复制
/**
 * Calculate a 32 bit FNV-1a hash
 * Found here: https://gist.github.com/vaiorabbit/5657561
 * Ref.: http://isthe.com/chongo/tech/comp/fnv/
 *
 * @param {string} str the input value
 * @param {boolean} [asString=false] set to true to return the hash value as 
 *     8-digit hex string instead of an integer
 * @param {integer} [seed] optionally pass the hash of the previous chunk
 * @returns {integer | string}
 */
function hashFnv32a(str, asString, seed) {
    /*jshint bitwise:false */
    var i, l,
        hval = (seed === undefined) ? 0x811c9dc5 : seed;

    for (i = 0, l = str.length; i < l; i++) {
        hval ^= str.charCodeAt(i);
        hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24);
    }
    if( asString ){
        // Convert to 8 digit hex string
        return ("0000000" + (hval >>> 0).toString(16)).substr(-8);
    }
    return hval >>> 0;
}

提高冲突概率

正如这里所解释的,我们可以使用这个技巧来扩展哈希位的大小:

代码语言:javascript
复制
function hash64(str) {
    var h1 = hash32(str);  // returns 32 bit (as 8 byte hex string)
    return h1 + hash32(h1 + str);  // 64 bit (as 16 byte hex string)
}

使用时要小心,但不要期望太高。

票数 125
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7616461

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档