Tôi cần chuyển đổi chuỗi thành một số dạng băm. Điều này có thể có trong JavaScript không?
Tôi không sử dụng ngôn ngữ phía máy chủ nên tôi không thể làm theo cách đó.
Tôi cần chuyển đổi chuỗi thành một số dạng băm. Điều này có thể có trong JavaScript không?
Tôi không sử dụng ngôn ngữ phía máy chủ nên tôi không thể làm theo cách đó.
Câu trả lời:
Object.defineProperty(String.prototype, 'hashCode', {
value: function() {
var hash = 0, i, chr;
for (i = 0; i < this.length; i++) {
chr = this.charCodeAt(i);
hash = ((hash << 5) - hash) + chr;
hash |= 0; // Convert to 32bit integer
}
return hash;
}
});
Nguồn: http://werxltd.com/wp/2010/05/13/javascript-imcellenceation-of-javas-opes-hashcode-method/
hash << 5 - hash
này giống như hash * 31 + char
nhưng rất nhiều nhanh hơn. Thật tuyệt vì nó quá nhanh, và 31 là một nguyên tố nhỏ. Giành chiến thắng ở đó.
(hash * 31) + char
giống hệt với đầu ra được tạo bởi mã dựa trên thay đổi ((hash<<5)-hash)+char
, ngay cả đối với các chuỗi rất dài (tôi đã kiểm tra nó với các chuỗi chứa hơn một triệu ký tự), vì vậy về mặt không "không sử dụng được" độ chính xác. Độ phức tạp là O (n) cho cả phiên bản dựa trên số và dịch chuyển, do đó, nó không "không sử dụng được" về độ phức tạp.
n
, thì giá trị lớn nhất n
mà tôi không thể có xung đột là bao nhiêu?
var hashCode = function hashCode (str) {etc...}
? Rồi dùng như hashCode("mystring")
thế nào?
BIÊN TẬP
dựa trên các bài kiểm tra jsperf của tôi, câu trả lời được chấp nhận thực sự nhanh hơn: http://jsperf.com/hashcodelordvlad
NGUYÊN
Nếu bất cứ ai quan tâm, đây là phiên bản cải tiến (nhanh hơn), sẽ thất bại trên các trình duyệt cũ thiếu reduce
chức năng mảng.
hashCode = function(s){
return s.split("").reduce(function(a,b){a=((a<<5)-a)+b.charCodeAt(0);return a&a},0);
}
phiên bản chức năng mũi tên một lớp lót:
hashCode = s => s.split('').reduce((a,b)=>{a=((a<<5)-a)+b.charCodeAt(0);return a&a},0)
Lưu ý: Ngay cả với hàm băm 32 bit tốt nhất, va chạm sẽ xảy ra sớm hay muộn.
Xác suất va chạm băm có thể được tính như , gần đúng như ( xem tại đây ). Điều này có thể cao hơn so với trực giác cho thấy:
Giả sử hàm băm 32 bit và k = 10.000 vật phẩm, một vụ va chạm sẽ xảy ra với xác suất 1,2%. Đối với 77.163 mẫu, xác suất trở thành 50%! ( máy tính ).
Tôi đề nghị một cách giải quyết ở phía dưới.
Trong câu trả lời cho câu hỏi này
Thuật toán băm nào là tốt nhất cho tính duy nhất và tốc độ? , Ian Boyd đã đăng một bài phân tích chuyên sâu . Nói tóm lại (như tôi giải thích), anh ta đi đến kết luận rằng Murmur là tốt nhất, tiếp theo là FNV-1a.
Thuật toán String.hashCode () của Java mà esmirusha đề xuất dường như là một biến thể của DJB2.
Một số điểm chuẩn có chuỗi đầu vào lớn tại đây: http://jsperf.com/32-bit-hash
Khi chuỗi đầu vào ngắn được băm, hiệu suất của murmur giảm, liên quan đến DJ2B và FNV-1a: http://jsperf.com/32- băm bit / 3
Vì vậy, nói chung tôi muốn giới thiệu murmur3.
Xem tại đây để triển khai JavaScript: https://github.com/ÿcourt / murmurhash- js
Nếu các chuỗi đầu vào ngắn và hiệu suất quan trọng hơn chất lượng phân phối, hãy sử dụng DJB2 (theo đề xuất của câu trả lời được chấp nhận bởi esmirusha).
Nếu chất lượng và kích thước mã nhỏ quan trọng hơn tốc độ, tôi sử dụng triển khai FNV-1a này (dựa trên mã này ).
/**
* Calculate a 32 bit FNV-1a hash
* Found here: https://gist.github.com/vaiorabbit/5657561
* Ref.: http://isthe.com/chongo/tech/comp/fnv/
*
* @param {string} str the input value
* @param {boolean} [asString=false] set to true to return the hash value as
* 8-digit hex string instead of an integer
* @param {integer} [seed] optionally pass the hash of the previous chunk
* @returns {integer | string}
*/
function hashFnv32a(str, asString, seed) {
/*jshint bitwise:false */
var i, l,
hval = (seed === undefined) ? 0x811c9dc5 : seed;
for (i = 0, l = str.length; i < l; i++) {
hval ^= str.charCodeAt(i);
hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24);
}
if( asString ){
// Convert to 8 digit hex string
return ("0000000" + (hval >>> 0).toString(16)).substr(-8);
}
return hval >>> 0;
}
Cải thiện xác suất va chạm
Như đã giải thích ở đây , chúng ta có thể mở rộng kích thước bit băm bằng thủ thuật này:
function hash64(str) {
var h1 = hash32(str); // returns 32 bit (as 8 byte hex string)
return h1 + hash32(h1 + str); // 64 bit (as 16 byte hex string)
}
Sử dụng cẩn thận và đừng mong đợi quá nhiều mặc dù.
("0000000" + (hval >>> 0).toString(16)).substr(-8);
vậy Điều đó có giống như (hval >>> 0).toString(16)
không?
hval
, (hval >>> 0).toString(16)
có thể có ít hơn 8 ký tự, vì vậy bạn đệm nó bằng số không. Tôi chỉ bối rối vì (hval >>> 0).toString(16)
luôn dẫn đến một chuỗi 8 ký tự chính xác cho tôi.
Math.imul
chức năng ES6 . Điều đó một mình làm cho nó điểm chuẩn hàng đầu, và cuối cùng là một lựa chọn tốt hơn so với DJB2 về lâu dài.
Dựa trên câu trả lời được chấp nhận trong ES6. Nhỏ hơn, có thể bảo trì và làm việc trong các trình duyệt hiện đại.
function hashCode(str) {
return str.split('').reduce((prevHash, currVal) =>
(((prevHash << 5) - prevHash) + currVal.charCodeAt(0))|0, 0);
}
// Test
console.log("hashCode(\"Hello!\"): ", hashCode('Hello!'));
EDIT (2019-11-04) :
phiên bản chức năng mũi tên một lớp lót:
const hashCode = s => s.split('').reduce((a,b) => (((a << 5) - a) + b.charCodeAt(0))|0, 0)
// test
console.log(hashCode('Hello!'))
str += ""
trước khi băm để tránh ngoại lệ str.split is not a function
bị ném khi các chuỗi không được truyền dưới dạng tham số
hash |= 0
để chuyển đổi thành int 32 bit. Việc thực hiện này không. Đây có phải là một lỗi?
Gần một nửa câu trả lời là các triển khai của Java
String.hashCode
, không phải là chất lượng cao hay siêu nhanh. Không có gì quá đặc biệt, nó chỉ nhân lên 31 cho mỗi nhân vật. Nó có thể được thực hiện đơn giản và hiệu quả trong một dòng và nhanh hơn nhiều vớiMath.imul
:
hashCode=s=>{for(var i=0,h;i<s.length;i++)h=Math.imul(31,h)+s.charCodeAt(i)|0;return h}
Ngoài ra, đây là một thứ gì đó tốt hơn trên mạng cyberb53 , một hàm băm 53 bit đơn giản nhưng chất lượng cao. Nó khá nhanh, cung cấp phân phối băm rất tốt và có tỷ lệ va chạm thấp hơn đáng kể so với bất kỳ hàm băm 32 bit nào.
const cyrb53 = function(str, seed = 0) {
let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed;
for (let i = 0, ch; i < str.length; i++) {
ch = str.charCodeAt(i);
h1 = Math.imul(h1 ^ ch, 2654435761);
h2 = Math.imul(h2 ^ ch, 1597334677);
}
h1 = Math.imul(h1 ^ h1>>>16, 2246822507) ^ Math.imul(h2 ^ h2>>>13, 3266489909);
h2 = Math.imul(h2 ^ h2>>>16, 2246822507) ^ Math.imul(h1 ^ h1>>>13, 3266489909);
return 4294967296 * (2097151 & h2) + (h1>>>0);
};
Tương tự như thuật toán MurmurHash / xxHash nổi tiếng, nó sử dụng kết hợp phép nhân và Xorshift để tạo ra hàm băm, nhưng không triệt để. Kết quả là nó nhanh hơn cả JavaScript và đơn giản hơn để thực hiện.
Nó đạt được tuyết lở (không nghiêm ngặt), về cơ bản có nghĩa là những thay đổi nhỏ trong đầu vào có những thay đổi lớn trong đầu ra, làm cho hàm băm kết quả xuất hiện ngẫu nhiên:
0xc2ba782c97901 = cyrb53("a")
0xeda5bc254d2bf = cyrb53("b")
0xe64cc3b748385 = cyrb53("revenge")
0xd85148d13f93a = cyrb53("revenue")
Bạn cũng có thể cung cấp một hạt giống cho các luồng thay thế của cùng một đầu vào:
0xee5e6598ccd5c = cyrb53("revenue", 1)
0x72e2831253862 = cyrb53("revenue", 2)
0x0de31708e6ab7 = cyrb53("revenue", 3)
Về mặt kỹ thuật, đó là hàm băm 64 bit (song song hai hàm băm 32 bit không tương thích), nhưng JavaScript bị giới hạn ở số nguyên 53 bit. Nếu được yêu cầu, đầu ra 64 bit đầy đủ vẫn có thể được sử dụng bằng cách thay đổi dòng trả về cho chuỗi hoặc mảng hex.
Xin lưu ý rằng việc xây dựng các chuỗi hex có thể làm chậm đáng kể quá trình xử lý hàng loạt trong các tình huống quan trọng về hiệu năng.
return (h2>>>0).toString(16).padStart(8,0)+(h1>>>0).toString(16).padStart(8,0);
// or
return [h2>>>0, h1>>>0];
Và chỉ để giải trí, đây là hàm băm tối thiểu 32 bit trong 89 ký tự với chất lượng cao hơn cả FNV hoặc DJB2:
TSH=s=>{for(var i=0,h=9;i<s.length;)h=Math.imul(h^s.charCodeAt(i++),9**9);return h^h>>>9}
ch
khởi tạo?
'imul'
.
Nếu nó giúp được bất cứ ai, tôi đã kết hợp hai câu trả lời hàng đầu thành một phiên bản cũ hơn cho trình duyệt, sử dụng phiên bản nhanh nếu reduce
có và quay lại giải pháp của esmirusha nếu không.
/**
* @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;
}
Cách sử dụng giống như:
var hash = "some string to be hashed".hashCode();
String.prototype.hashCode = function(){ var hash = 5381; if (this.length === 0) return hash; for (var i = 0; i < this.length; i++) { var character = this.charCodeAt(i); hash = ((hash<<5)+hash)^character; // Convert to 32bit integer } return hash; }
Đây là một biến thể tinh chế và hoạt động tốt hơn:
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;
};
Điều này phù hợp với việc triển khai tiêu chuẩn của Java object.hashCode()
Đây cũng là một trong đó chỉ trả về mã băm tích cực:
String.prototype.hashcode = function() {
return (this.hashCode() + 2147483647) + 1;
};
Và đây là một kết hợp phù hợp với Java chỉ trả về mã băm tích cực:
public static long hashcode(Object obj) {
return ((long) obj.hashCode()) + Integer.MAX_VALUE + 1l;
}
Thưởng thức!
Tôi hơi ngạc nhiên khi chưa có ai nói về API SubicateCrypto mới .
Để có được một hàm băm từ một chuỗi, bạn có thể sử dụng subtle.digest
phương thức:
function getHash(str, algo = "SHA-256") {
let strBuf = new TextEncoder('utf-8').encode(str);
return crypto.subtle.digest(algo, strBuf)
.then(hash => {
window.hash = hash;
// here hash is an arrayBuffer,
// so we'll connvert it to its hex version
let result = '';
const view = new DataView(hash);
for (let i = 0; i < hash.byteLength; i += 4) {
result += ('00000000' + view.getUint32(i).toString(16)).slice(-8);
}
return result;
});
}
getHash('hello world')
.then(hash => {
console.log(hash);
});
var promise = crypto.subtle.digest({name: "SHA-256"}, Uint8Array.from(data)); promise.then(function(result){ console.log(Array.prototype.map.call(new Uint8Array(result), x => x.toString(16).padStart(2, '0')).join('')); });
crypto
không chính xác là hiệu suất.
Nhờ ví dụ của mar10, tôi đã tìm ra cách để có được kết quả tương tự trong C # VÀ Javascript cho FNV-1a. Nếu ký tự unicode có mặt, phần trên bị loại bỏ vì lợi ích của hiệu suất. Không biết tại sao sẽ hữu ích khi duy trì những thứ đó khi băm, vì hiện tại chỉ băm các đường dẫn url.
Phiên bản 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());
}
Phiên bản 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);
}
Math.imul
có thể được sử dụng cho bước nhân, giúp cải thiện đáng kể hiệu suất . Chỉ vấn đề là, nó sẽ không làm việc trong IE11 mà không có một shim .
Tôi cần một chức năng tương tự (nhưng khác nhau) để tạo ID-ish duy nhất dựa trên tên người dùng và thời gian hiện tại. Vì thế:
window.newId = ->
# create a number based on the username
unless window.userNumber?
window.userNumber = 0
for c,i in window.MyNamespace.userName
char = window.MyNamespace.userName.charCodeAt(i)
window.MyNamespace.userNumber+=char
((window.MyNamespace.userNumber + Math.floor(Math.random() * 1e15) + new Date().getMilliseconds()).toString(36)).toUpperCase()
Sản xuất:
2DVFXJGEKL
6IZPAKFQFL
ORGOENVMG
... etc
chỉnh sửa tháng 6 năm 2015: Đối với mã mới, tôi sử dụng shortid: https://www.npmjs.com/package/shortid
Một lớp lót nhanh (rất dài) của tôi dựa trên Multiply+Xor
phương pháp của FNV :
my_string.split('').map(v=>v.charCodeAt(0)).reduce((a,v)=>a+((a<<7)+(a<<3))^v).toString(16);
Tôi không sử dụng ngôn ngữ phía máy chủ nên tôi không thể làm theo cách đó.
Bạn có chắc là bạn không thể làm theo cách đó ?
Bạn có quên bạn đang sử dụng Javascript, ngôn ngữ luôn phát triển?
Hãy thử SubtleCrypto
. Nó hỗ trợ các hàm băm SHA-1, SHA-128, SHA-256 và SHA-512.
async function hash(message/*: string */) {
const text_encoder = new TextEncoder;
const data = text_encoder.encode(message);
const message_digest = await window.crypto.subtle.digest("SHA-512", data);
return message_digest;
} // -> ArrayBuffer
function in_hex(data/*: ArrayBuffer */) {
const octets = new Uint8Array(data);
const hex = [].map.call(octets, octet => octet.toString(16).padStart(2, "0")).join("");
return hex;
} // -> string
(async function demo() {
console.log(in_hex(await hash("Thanks for the magic.")));
})();
Tôi kinda muộn để đảng, nhưng bạn có thể sử dụng mô-đun này: crypto :
const crypto = require('crypto');
const SALT = '$ome$alt';
function generateHash(pass) {
return crypto.createHmac('sha256', SALT)
.update(pass)
.digest('hex');
}
Kết quả của hàm này luôn là 64
chuỗi ký tự; đại loại như thế này:"aa54e7563b1964037849528e7ba068eb7767b1fab74a8d80fe300828b996714a"
Tôi đã kết hợp hai giải pháp (người dùng esmirusha và lordvlad) để có được một chức năng nên nhanh hơn cho các trình duyệt hỗ trợ chức năng js giảm () và vẫn tương thích với các trình duyệt cũ:
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;
}
};
Thí dụ:
my_string = 'xyz';
my_string.hashCode();
Nếu bạn muốn tránh va chạm, bạn có thể muốn sử dụng hàm băm an toàn như SHA-256 . Có một số triển khai JavaScript SHA-256.
Tôi đã viết các bài kiểm tra để so sánh một số triển khai băm, xem https://github.com/brillout/test-javascript-hash-im THỰCations .
Hoặc truy cập http://brillout.github.io/test-javascript-hash-im THỰCations / , để chạy thử nghiệm.
Đây phải là hàm băm an toàn hơn một chút so với một số câu trả lời khác, nhưng trong một hàm, không có bất kỳ nguồn tải trước nào
Về cơ bản, tôi đã tạo ra một phiên bản đơn giản hóa của sha1.
Bạn lấy các byte của chuỗi và nhóm chúng theo 4 đến 32 bit "từ"
Sau đó, chúng tôi mở rộng 8 từ thành 40 từ (để có tác động lớn hơn đến kết quả).
Điều này đi đến hàm băm (mức giảm cuối cùng) trong đó chúng ta thực hiện một số phép toán với trạng thái hiện tại và đầu vào. Chúng tôi luôn nhận được 4 từ.
Đây gần như là phiên bản một lệnh / một dòng sử dụng bản đồ, giảm ... thay vì các vòng lặp, nhưng nó vẫn khá nhanh
String.prototype.hash = function(){
var rot = (word, shift) => word << shift | word >>> (32 - shift);
return unescape(encodeURIComponent(this.valueOf())).split("").map(char =>
char.charCodeAt(0)
).reduce((done, byte, idx, arr) =>
idx % 4 == 0 ? [...done, arr.slice(idx, idx + 4)] : done
, []).reduce((done, group) =>
[...done, group[0] << 24 | group[1] << 16 | group[2] << 8 | group[3]]
, []).reduce((done, word, idx, arr) =>
idx % 8 == 0 ? [...done, arr.slice(idx, idx + 8)] : done
, []).map(group => {
while(group.length < 40)
group.push(rot(group[group.length - 2] ^ group[group.length - 5] ^ group[group.length - 8], 3));
return group;
}).flat().reduce((state, word, idx, arr) => {
var temp = ((state[0] + rot(state[1], 5) + word + idx + state[3]) & 0xffffffff) ^ state[idx % 2 == 0 ? 4 : 5](state[0], state[1], state[2]);
state[0] = rot(state[1] ^ state[2], 11);
state[1] = ~state[2] ^ rot(~state[3], 19);
state[2] = rot(~state[3], 11);
state[3] = temp;
return state;
}, [0xbd173622, 0x96d8975c, 0x3a6d1a23, 0xe5843775,
(w1, w2, w3) => (w1 & rot(w2, 5)) | (~rot(w1, 11) & w3),
(w1, w2, w3) => w1 ^ rot(w2, 5) ^ rot(w3, 11)]
).slice(0, 4).map(p =>
p >>> 0
).map(word =>
("0000000" + word.toString(16)).slice(-8)
).join("");
};
chúng tôi cũng chuyển đổi đầu ra thành hex để lấy một chuỗi thay vì mảng từ.
Cách sử dụng rất đơn giản. cho mẫu "a string".hash()
sẽ trở lại"88a09e8f9cc6f8c71c4497fbb36f84cd"
Tôi đã thực hiện một cách ghép đơn giản các mã char được chuyển đổi thành các chuỗi hex. Điều này phục vụ một mục đích tương đối hẹp, cụ thể là chỉ cần một biểu diễn băm của chuỗi SHORT (ví dụ như tiêu đề, thẻ) để được trao đổi với phía máy chủ mà không có lý do liên quan có thể dễ dàng thực hiện cổng Java hashCode được chấp nhận. Rõ ràng không có ứng dụng bảo mật ở đây.
String.prototype.hash = function() {
var self = this, range = Array(this.length);
for(var i = 0; i < this.length; i++) {
range[i] = i;
}
return Array.prototype.map.call(range, function(i) {
return self.charCodeAt(i).toString(16);
}).join('');
}
Điều này có thể được thực hiện nhanh hơn và chấp nhận trình duyệt với Underscore. Thí dụ:
"Lorem Ipsum".hash()
"4c6f72656d20497073756d"
Tôi cho rằng nếu bạn muốn băm các chuỗi lớn hơn theo cách tương tự, bạn chỉ có thể giảm mã char và hex hóa tổng kết quả thay vì nối các ký tự riêng lẻ lại với nhau:
String.prototype.hashLarge = function() {
var self = this, range = Array(this.length);
for(var i = 0; i < this.length; i++) {
range[i] = i;
}
return Array.prototype.reduce.call(range, function(sum, i) {
return sum + self.charCodeAt(i);
}, 0).toString(16);
}
'One time, I hired a monkey to take notes for me in class. I would just sit back with my mind completely blank while the monkey scribbled on little pieces of paper. At the end of the week, the teacher said, "Class, I want you to write a paper using your notes." So I wrote a paper that said, "Hello! My name is Bingo! I like to climb on things! Can I have a banana? Eek, eek!" I got an F. When I told my mom about it, she said, "I told you, never trust a monkey!"'.hashLarge()
"9ce7"
Đương nhiên, nguy cơ va chạm với phương pháp này sẽ cao hơn, mặc dù bạn có thể sử dụng số học trong phần giảm nhưng bạn muốn đa dạng hóa và kéo dài hàm băm.
Phiên bản đơn giản hóa của câu trả lời của @ esmirusha.
Tôi không ghi đè Chuỗi trong phiên bản này, vì điều đó có thể dẫn đến một số hành vi không mong muốn.
function hashCode(str) {
var hash = 0;
for (var i = 0; i < str.length; i++) {
hash = ~~(((hash << 5) - hash) + str.charCodeAt(i));
}
return hash;
}
Thêm điều này bởi vì chưa ai làm, và điều này dường như được yêu cầu và thực hiện rất nhiều với băm, nhưng nó luôn được thực hiện rất kém ...
Điều này nhận đầu vào chuỗi và số lượng tối đa bạn muốn hàm băm bằng nhau và tạo ra một số duy nhất dựa trên đầu vào chuỗi.
Bạn có thể sử dụng điều này để tạo một chỉ mục duy nhất thành một mảng hình ảnh (Nếu bạn muốn trả lại một hình đại diện cụ thể cho người dùng, được chọn ngẫu nhiên, nhưng cũng được chọn dựa trên tên của họ, vì vậy nó sẽ luôn được gán cho người có tên đó ).
Tất nhiên, bạn cũng có thể sử dụng điều này để trả về một chỉ mục thành một mảng màu, như để tạo màu nền avatar độc đáo dựa trên tên của ai đó.
function hashInt (str, max = 1000) {
var hash = 0;
for (var i = 0; i < str.length; i++) {
hash = ((hash << 5) - hash) + str.charCodeAt(i);
hash = hash & hash;
}
return Math.round(max * Math.abs(hash) / 2147483648);
}
Tôi không thấy bất kỳ lý do nào để sử dụng mã tiền điện tử quá phức tạp này thay vì các giải pháp sẵn sàng sử dụng, như thư viện băm đối tượng, v.v. dựa vào nhà cung cấp sẽ hiệu quả hơn, tiết kiệm thời gian và giảm chi phí bảo trì.
Chỉ cần sử dụng https://github.com/puleos/object-hash
var hash = require('object-hash');
hash({foo: 'bar'}) // => '67b69634f9880a282c14a0f0cb7ba20cf5d677e9'
hash([1, 2, 2.718, 3.14159]) // => '136b9b88375971dff9f1af09d7356e3e04281951'
var crypto = require('crypto');
. Tôi nghĩ rằng nó thêm mã phụ thuộc này từ nhà cung cấp trong phiên bản rút gọn trong quá trình xây dựng.