9

Создание хеша из строки в JavaScript

23

Мне нужно преобразовать строки в некую форму хеша. Это возможно сделать на JavaScript?

Я не использую серверный язык, поэтому не могу сделать это таким образом.

5 ответ(ов)

2

ИЗМЕНЕНИЕ

На основе моих тестов jsperf, принятый ответ на самом деле быстрее: http://jsperf.com/hashcodelordvlad

ОРИГИНАЛ

Если кто-то заинтересован, вот улучшенная (более быстрая) версия, которая не будет работать в старых браузерах, в которых отсутствует функция reduce для массивов.

hashCode = function(s) {
  return s.split("").reduce(function(a, b) {
    a = ((a << 5) - a) + b.charCodeAt(0);
    return a & a;
  }, 0);
}
 
// тестирование
console.log(hashCode("hello."));
console.log(hashCode("this is a text."));
console.log(hashCode("Despacito by Luis Fonsi"));

Версия в одну строку с использованием стрелочных функций:

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

// тестирование
console.log(hashCode("hello."));
console.log(hashCode("this is a text."));
console.log(hashCode("Despacito by Luis Fonsi"));
0

Это усовершенствованный и более производительный вариант, который совпадает с реализацией стандартного метода object.hashCode() для CharSequence в Java.

Вот пример реализации для String в JavaScript:

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

Также есть вариант, который возвращает только положительные хеш-коды:

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

И вот соответствующий метод для Java, который также возвращает только положительные хеш-коды:

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

Для тех, кто не хочет добавлять методы к String, можно использовать функции без добавления в прототип:

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

function hashcode(str) {
    return hashCode(str) + 2147483647 + 1;
}

Наслаждайтесь!

0

Если это будет полезно кому-то, я объединил два лучших ответа в версию, совместимую со старыми браузерами. В этом коде используется быстрая версия, если доступен метод reduce, и в случае его отсутствия применяется решение esmiralha.

/**
 * @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; // Преобразование в 32-битное целое
    }
    return hash;
}

Использование выглядит так:

var hash = "некоторый строка для хеширования".hashCode();
0

Вот компактный и удобочитаемый код на ES6:

const stringHashCode = str => {
  let hash = 0;
  for (let i = 0; i < str.length; ++i)
    hash = Math.imul(31, hash) + str.charCodeAt(i);

  return hash | 0;
}

Этот фрагмент кода вычисляет хэш-код для строки str с использованием простого алгоритма. Он проходит по каждому символу строки, вычисляет его код с помощью charCodeAt(i) и обновляет хэш с помощью Math.imul, чтобы избежать переполнения при умножении. В конце результат преобразуется в 32-битное целое число с помощью побитовой операции OR с нулем.

0

Ваш код использует метод Multiply+Xor на основе алгоритма FNV для хеширования строки и представлен в виде однострочника. Давайте разберем его:

my_string.split('').map(v => v.charCodeAt(0))
  .reduce((a, v) => a + ((a << 7) + (a << 3)) ^ v)
  .toString(16);
  1. my_string.split(''): Делит строку my_string на массив символов.
  2. .map(v => v.charCodeAt(0)): Преобразует каждый символ в его числовое значение (код символа).
  3. .reduce((a, v) => a + ((a << 7) + (a << 3)) ^ v): Накапливает значения, используя левый сдвиг и оператор XOR для получения итогового результата.
  4. .toString(16): Преобразует полученное значение в шестнадцатеричное представление.

Этот подход достаточно компактен и эффективен для хеширования строк. Не забудьте, что для больших строк могут быть потенциальные переполнения, поэтому, если ваши данные могут быть весьма крупными, рассмотрите возможность обработки переполнений.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь