Generiere einen Hash von String in Javascript / jQuery


Answers

BEARBEITEN

basierend auf meinen Jsperf-Tests ist die akzeptierte Antwort tatsächlich schneller: http://jsperf.com/hashcodelordvlad

ORIGINAL

Wenn jemand daran interessiert ist, ist hier eine verbesserte (schnellere) Version, die bei älteren Browsern fehlschlägt, denen die Funktion "Array reduce fehlt.

hashCode = function(s){
  return s.split("").reduce(function(a,b){a=((a<<5)-a)+b.charCodeAt(0);return a&a},0);              
}
Question

Ich muss Zeichenfolgen in irgendeine Form von Hash konvertieren. Ist das in Javascript / jQuery möglich?

Ich benutze keine serverseitige Sprache, also kann ich es nicht so machen.




Basierend auf akzeptierter Antwort in ES6. Kleiner, wartbar und funktioniert in modernen Browsern.

function hashCode(str) {
  return str.split('').reduce((prevHash, currVal) =>
    (((prevHash << 5) - prevHash) + currVal.charCodeAt(0))|0, 0);
}

// Test
console.log("hashCode(\"Hello!\"): ", hashCode('Hello!'));







Ich habe die beiden Lösungen (Benutzer esmiralha und lordvlad) kombiniert, um eine Funktion zu erhalten, die für Browser, die die js-Funktion reduce () unterstützen und noch mit alten Browsern kompatibel sind, schneller sein sollte:

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);   
    } else {

        var hash = 0, i, chr, len;
        if (this.length == 0) return hash;
        for (i = 0, len = this.length; i < len; i++) {
        chr   = this.charCodeAt(i);
        hash  = ((hash << 5) - hash) + chr;
        hash |= 0; // Convert to 32bit integer
        }
        return hash;
    }
};

Beispiel:

my_string = 'xyz';
my_string.hashCode();



Mit dieser Lösung können wir den Zeichensatz angeben, um einige Probleme zu vermeiden, wenn die Werte zwischen Anwendungsebenen gespeichert oder gesendet werden, zum Beispiel: Wenn der Ergebnisstring (Hash) eine prozentuale Codierung erzeugt und diese Zeichenfolge über die GET-Methode an den Controller gesendet wird Schicht.

function doHashCode() {
    String.prototype.hashCode = function () {
        var text = "";
        var possible = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

        for (var i = 0; i < 15; i++)
            text += possible.charAt(Math.floor(Math.random() * possible.length));
        return text;
    }

    var hash = new String().hashCode();
    $('#input-text-hash').val(hash); // your html input text

}



Dies ist eine raffinierte und leistungsstärkere Variante:

String.prototype.hashCode = function() {
    var hash = 0, i = 0, len = this.length;
    while ( i < len ) {
        hash  = ((hash << 5) - hash + this.charCodeAt(i++)) << 0;
    }
    return hash;
};

Dies entspricht der Java-Implementierung des Standards object.hashCode()

Hier ist auch eine, die nur positive Hashcodes zurückgibt:

String.prototype.hashcode = function() {
    return (this.hashCode() + 2147483647) + 1;
};

Und hier ist eine passende für Java, die nur positive Hashcodes zurückgibt:

public static long hashcode(Object obj) {
    return ((long) obj.hashCode()) + Integer.MAX_VALUE + 1l;
}

Genießen!




Dank dem Beispiel von mar10 habe ich einen Weg gefunden, die gleichen Ergebnisse in C # AND Javascript für einen FNV-1a zu erhalten. Wenn Unicode-Zeichen vorhanden sind, wird der obere Teil aus Gründen der Leistung verworfen. Ich weiß nicht, warum es hilfreich wäre, diese beim Hashing beizubehalten, da ich erst jetzt URL-Pfade hashe.

C # Version

private static readonly UInt32 FNV_OFFSET_32 = 0x811c9dc5;   // 2166136261
private static readonly UInt32 FNV_PRIME_32 = 0x1000193;     // 16777619

// Unsigned 32bit integer FNV-1a
public static UInt32 HashFnv32u(this string s)
{
    // byte[] arr = Encoding.UTF8.GetBytes(s);      // 8 bit expanded unicode array
    char[] arr = s.ToCharArray();                   // 16 bit unicode is native .net 

    UInt32 hash = FNV_OFFSET_32;
    for (var i = 0; i < s.Length; i++)
    {
        // Strips unicode bits, only the lower 8 bits of the values are used
        hash = hash ^ unchecked((byte)(arr[i] & 0xFF));
        hash = hash * FNV_PRIME_32;
    }
    return hash;
}

// Signed hash for storing in SQL Server
public static Int32 HashFnv32s(this string s)
{
    return unchecked((int)s.HashFnv32u());
}

JavaScript-Version

var utils = utils || {};

utils.FNV_OFFSET_32 = 0x811c9dc5;

utils.hashFnv32a = function (input) {
    var hval = utils.FNV_OFFSET_32;

    // Strips unicode bits, only the lower 8 bits of the values are used
    for (var i = 0; i < input.length; i++) {
        hval = hval ^ (input.charCodeAt(i) & 0xFF);
        hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24);
    }

    return hval >>> 0;
}

utils.toHex = function (val) {
    return ("0000000" + (val >>> 0).toString(16)).substr(-8);
}



Eine schnelle und prägnante, die von here aus angepasst here :

String.prototype.hashCode = function() {
  var hash = 5381, i = this.length
  while(i)
    hash = (hash * 33) ^ this.charCodeAt(--i)
  return hash >>> 0;
}