Skip to content

Instantly share code, notes, and snippets.

@hyamamoto
Created September 30, 2016 07:19
  • Star 65 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
Star You must be signed in to star a gist
Embed
What would you like to do?
JavaScript Implementation of String.hashCode() .
/**
* Returns a hash code for a string.
* (Compatible to Java's String.hashCode())
*
* The hash code for a string object is computed as
* s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
* using number arithmetic, where s[i] is the i th character
* of the given string, n is the length of the string,
* and ^ indicates exponentiation.
* (The hash value of the empty string is zero.)
*
* @param {string} s a string
* @return {number} a hash code value for the given string.
*/
hashCode = function(s) {
var h = 0, l = s.length, i = 0;
if ( l > 0 )
while (i < l)
h = (h << 5) - h + s.charCodeAt(i++) | 0;
return h;
};
> hashCode('')
0
> hashCode('Hello')
69609650
@bryc
Copy link

bryc commented Aug 31, 2018

Faster version using ES6 Math.imul for fun!

function hashCode(s) {
    for(var i = 0, h = 0; i < s.length; i++)
        h = Math.imul(31, h) + s.charCodeAt(i) | 0;
    return h;
}

If you're wondering about the | 0 part, it forces h to be a 32-bit number, optimizing for speed in JS engines.

@eliurkis
Copy link

eliurkis commented Nov 21, 2018

Using let

function hashCode(s) {
    for(let i = 0, h = 0; i < s.length; i++)
        h = Math.imul(31, h) + s.charCodeAt(i) | 0;

    return h;
}

@4nte
Copy link

4nte commented Dec 3, 2018

Using let

function hashCode(s) {
    for(let i = 0, h = 0; i < s.length; i++)
        h = Math.imul(31, h) + s.charCodeAt(i) | 0;

    return h;
}

Since you've changed var to let, variable h now must be declared outside the for loop.

function hashCode(s) {
    let h;
    for(let i = 0; i < s.length; i++) 
          h = Math.imul(31, h) + s.charCodeAt(i) | 0;

    return h;
}

@ORESoftware
Copy link

What about a hashCode of an object in JS? Maybe that can only happen in C/C++ land.

@bryc
Copy link

bryc commented Dec 9, 2018

@jschirrmacher
Copy link

Alternative using arrays:

function hashCode(str) {
  return Array.from(str)
    .reduce((s, c) => Math.imul(31, s) + c.charCodeAt(0) | 0, 0)
}

@igium
Copy link

igium commented Mar 6, 2020

Thank you.

hashCode = function(s) {
  var h = 0, i = s.length - 1;
    while (i >= 0)
      h = (h << 5) - h + s.charCodeAt(--i) | 0;
  return h;
};

One less local variable and one less if.

@max-s-h
Copy link

max-s-h commented Jan 7, 2021

the last char will be ignored and in a last iteration you try to take charCode for -1

hashCode = function(s) {
    var h = 0, i = s.length;
    while (i > 0) {
        h = (h << 5) - h + s.charCodeAt(--i) | 0;
    }
    return h; 
};

@blackjackshellac
Copy link

Using let

function hashCode(s) {
    for(let i = 0, h = 0; i < s.length; i++)
        h = Math.imul(31, h) + s.charCodeAt(i) | 0;

    return h;
}

Since you've changed var to let, variable h now must be declared outside the for loop.

function hashCode(s) {
    let h;
    for(let i = 0; i < s.length; i++) 
          h = Math.imul(31, h) + s.charCodeAt(i) | 0;

    return h;
}

For s.length === 0 :)

function hashCode(s) {
    let h=0;
    for(let i = 0; i < s.length; i++) 
          h = Math.imul(31, h) + s.charCodeAt(i) | 0;

    return h;
}

@ArashPartow
Copy link

A comprehensive list of general purpose hash functions and their implementations can found here:

https://www.partow.net/programming/hashfunctions/index.html

@eru123
Copy link

eru123 commented Aug 10, 2022

Alternative using arrays:

function hashCode(str) {
  return Array.from(str)
    .reduce((s, c) => Math.imul(31, s) + c.charCodeAt(0) | 0, 0)
}

A one liner version

const hashCode = (str) => [...str].reduce((s, c) => Math.imul(31, s) + c.charCodeAt(0) | 0, 0) 

@tiagofrancafernandes
Copy link

Source: https://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript

/**
 * @see http://stackoverflow.com/q/7616461/940217
 * @return {number}
 */
String.prototype.hashCode = function(){
    if (Array.prototype.reduce){
        return this.split("").reduce(function(a,b){a=((a<<5)-a)+b.charCodeAt(0);return a&a},0);              
    } 
    var hash = 0;
    if (this.length === 0) return hash;
    for (var i = 0; i < this.length; i++) {
        var character  = this.charCodeAt(i);
        hash  = ((hash<<5)-hash)+character;
        hash = hash & hash; // Convert to 32bit integer
    }
    return hash;
}

Use:

console.log(
	String('[').hashCode(),
	String('a').hashCode(),
	String(']').hashCode(),
	String('[a]').hashCode(),
	String('[a]').hashCode()
)

// Output:
// 91 97 93 90551 90551

@tiagofrancafernandes
Copy link

/**
 * Returns a UUIDv4 as string
 *
 * @returns {string}
 */
generateUuid = () => {
    return (
        String('xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx')
    ).replace(/[xy]/g, (character) => {
        const random = (Math.random() * 16) | 0;
        const value = character === "x" ? random : (random & 0x3) | 0x8;

        return value.toString(16);
    });
};

generateUuid()

@Super-Chama
Copy link

Super-Chama commented May 4, 2023

Here's even faster implementation of the original using ES6 reduce.

function hashCode(s) {
  return [...s].reduce(
    (hash, c) => (Math.imul(31, hash) + c.charCodeAt(0)) | 0,
    0
  );
}

Tested in Chrome (112.0 v)

  • Original (while loop): 2.40087890625 ms
  • Modified (for loop): 3.412109375 ms
  • New (reduce): 1.150146484375 ms

@martin-juul
Copy link

@Super-Chama you copied the answer from @4nte ...

@Super-Chama
Copy link

@martin-juul no, look again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment