Создание хеша из строки в JavaScript
Мне нужно преобразовать строки в некую форму хеша. Это возможно сделать на JavaScript?
Я не использую серверный язык, поэтому не могу сделать это таким образом.
5 ответ(ов)
ИЗМЕНЕНИЕ
На основе моих тестов 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"));
Это усовершенствованный и более производительный вариант, который совпадает с реализацией стандартного метода 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;
}
Наслаждайтесь!
Если это будет полезно кому-то, я объединил два лучших ответа в версию, совместимую со старыми браузерами. В этом коде используется быстрая версия, если доступен метод 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();
Вот компактный и удобочитаемый код на 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 с нулем.
Ваш код использует метод Multiply+Xor
на основе алгоритма FNV для хеширования строки и представлен в виде однострочника. Давайте разберем его:
my_string.split('').map(v => v.charCodeAt(0))
.reduce((a, v) => a + ((a << 7) + (a << 3)) ^ v)
.toString(16);
my_string.split('')
: Делит строкуmy_string
на массив символов..map(v => v.charCodeAt(0))
: Преобразует каждый символ в его числовое значение (код символа)..reduce((a, v) => a + ((a << 7) + (a << 3)) ^ v)
: Накапливает значения, используя левый сдвиг и оператор XOR для получения итогового результата..toString(16)
: Преобразует полученное значение в шестнадцатеричное представление.
Этот подход достаточно компактен и эффективен для хеширования строк. Не забудьте, что для больших строк могут быть потенциальные переполнения, поэтому, если ваши данные могут быть весьма крупными, рассмотрите возможность обработки переполнений.
Как перенаправить на другую веб-страницу?
Где найти документацию по форматированию даты в JavaScript?
Как выполнить функцию JavaScript, имея её имя в виде строки
В чем разница между String.slice и String.substring?
Проверка соответствия строки регулярному выражению в JS