Genera un hash da una stringa in Javascript / jQuery


Answers

MODIFICARE

basato sui miei test jsperf, la risposta accettata è in realtà più veloce: http://jsperf.com/hashcodelordvlad

ORIGINALE

se qualcuno è interessato, ecco una versione migliorata (più veloce), che fallirà sui browser più vecchi che non hanno la funzione di reduce dell'array.

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

Ho bisogno di convertire stringhe in una qualche forma di hash. È possibile in Javascript / jQuery?

Non sto utilizzando un linguaggio lato server, quindi non posso farlo in quel modo.




Grazie all'esempio di mar10, ho trovato un modo per ottenere gli stessi risultati in C # e Javascript per un FNV-1a. Se sono presenti caratteri unicode, la parte superiore viene scartata per motivi di prestazioni. Non so perché sarebbe utile per mantenere quelli quando hashing, come sono solo percorsi di URL hashing per ora.

Versione C #

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());
}

Versione JavaScript

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



Con questa soluzione possiamo specificare il set di caratteri per evitare alcuni problemi quando i valori vengono memorizzati o inviati tra i livelli dell'applicazione, ad esempio: Quando la stringa risultato (hash) produce la codifica percentuale e quella stringa viene inviata al controller usando il metodo GET dalla vista strato.

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

}



Uno veloce e conciso che è stato adattato da here :

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






Ho combinato le due soluzioni (utenti esmiralha e lordvlad) per ottenere una funzione che dovrebbe essere più veloce per i browser che supportano la funzione js reduce () e comunque compatibile con i vecchi browser:

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;
    }
};

Esempio:

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



Basato sulla risposta accettata in ES6. Più piccolo, manutenibile e funziona nei browser moderni.

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

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




Questa è una variante raffinata e migliore:

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;
};

object.hashCode() all'applicazione Java dello standard object.hashCode()

Ecco anche uno che restituisce solo hashcode positivi:

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

Ed ecco un matching per Java che restituisce solo hashcode positivi:

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

Godere!




Related