„JavaScript“ versijos sukūrimas iš eilutės

Turiu konvertuoti eilutes į tam tikrą maišos formą. Ar tai įmanoma JavaScript?

Aš nenaudoju serverio kalbos, todėl negaliu to padaryti.

433
01 окт. nustatė FreeSnow spalio 01 d 2011-10-01 00:52 '11 prie 0:52 2011-10-01 00:52
@ 18 atsakymų
 String.prototype.hashCode = function() { var hash = 0, i, chr; if (this.length === 0) return hash; for (i = 0; i < this.length; i++) { chr = this.charCodeAt(i); hash = ((hash << 5) - hash) + chr; hash |= 0; // Convert to 32bit integer } return hash; }; 

Šaltinis: http://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/

637
01 окт. atsakymas pateikiamas esmiralha 01 okt. 2011-10-01 00:55 '11 prie 0:55 2011-10-01 00:55

PAKEITIMAS

remiantis mano „jsperf“ testais, priimtas atsakymas iš tiesų yra greitesnis: http://jsperf.com/hashcodelordvlad

ORIGINAL

jei kas nors domisi, čia yra patobulinta (greitesnė) versija, kuri neveiks senesnėse naršyklėse, kuriose trūksta reduce masyvo funkcijos.

 hashCode = function(s){ return s.split("").reduce(function(a,b){a=((a<<5)-a)+b.charCodeAt(0);return a } 
107
29 марта '13 в 23:09 2013-03-29 23:09 atsakymą pateikė lordvlad , kovo 29 d. 13 val. 23:09 2013-03-29 23:09

Pastaba: Net ir su geriausiais 32 bitų maišais turėsite susidoroti su tuo, kad susidūrimai įvyksta anksčiau ar vėliau. Tai reiškia, kad dvi skirtingos įvesties linijos grąžina tą pačią maišos reikšmę bent 1: 2 ^ 32 tikimybei.

Atsakydami į šį klausimą, koks maišymo algoritmas geriausiai tinka unikalumui ir greičiui? Ian Boyd paskelbė gerą išsamią analizę . Trumpai tariant, jis aiškina, kad Murmur yra geresnis, o tada FNV-1a.
Esmiralha pasiūlytas javas String.hashCode () atrodo DJB2 variantas.

  • FNV-1a turi geresnį paskirstymą nei DJB2, bet lėčiau
  • DJB2 yra greitesnis nei FNV-1a, tačiau yra linkęs suteikti daugiau susidūrimų
  • „MurmurHash3“ yra geresnis ir greitesnis nei DJB2 ir FNV-1a (tačiau optimizuotam diegimui reikia daugiau kodų nei FNV ir DJB2)

Kai kurie bandymai su didelėmis įvesties linijomis yra čia: http://jsperf.com/32-bit-hash
Kai trumpos įvesties linijos yra sugadintos, grumbėjimo lašų našumas lyginant su DJ2B ir FNV-1a: http://jsperf.com/32-bit-hash/3

Taigi apskritai, aš norėčiau rekomenduoti murmur3.
Žr. Čia „JavaScript“ diegimą: https://github.com/garycourt/murmurhash-js

Jei įvesties linijos yra trumpos ir našumas yra svarbesnis už platinimo kokybę, naudokite DJB2 (kaip siūlė esmiralha priimtas atsakymas).

Jei kokybė ir mažas kodo dydis yra svarbesni už greitį, naudoju šį FNV-1a įgyvendinimą (remiantis šiuo kodu ).

  function hashFnv32a(str, asString, seed) {  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; } 
75
16 марта '14 в 0:01 2014-03-16 00:01 atsakymas pateikiamas kovo 10 d., kovo 14 d., 14 val. 0:01 2014-03-16 00:01

Remiantis ES6 gautu atsakymu . Mažesnės, palaikomos ir veikia šiuolaikinėse naršyklėse.

39
17 янв. Atsakymas pateikiamas deekshith sausio 17 d 2016-01-17 22:41 '16 at 10:41 pm 2016-01-17 22:41

Jei tai padeda kam nors, aš sujungiau du vyresnius atsakymus versijoje su senesne naršykle, kuri naudoja greitąją versiją, jei reduce , ir grįžta į esmiralha sprendimą, jei ne.

  String.prototype.hashCode = function(){ if (Array.prototype.reduce){ return this.split("").reduce(function(a,b){a=((a<<5)-a)+b.charCodeAt(0);return a } 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; } 

Naudoti:

 var hash = new String("some string to be hashed").hashCode(); 
24
23 нояб. Kyle Falconer atsakymas lapkričio 23 d 2013-11-23 01:54 '13 ne 1:54 2013-11-23 01:54

Tai yra patobulintas ir efektyvesnis pasirinkimas:

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

Tai atitinka „ object.hashCode() standarto „Java“ įgyvendinimą object.hashCode()

Čia yra vienas, kuris grąžina tik teigiamus maišos kodus:

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

Ir čia jis tinka „Java“, kuris grąžina tik teigiamus maišos kodus:

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

Mėgaukitės!

17
11 нояб. Atsakymą pateikė momomo 11 lapkričio. 2015-11-11 12:43 '15, 12:43, 2015-11-11 12:43

Aš šiek tiek nustebęs, kad niekas nekalbėjo apie naują „ SubtleCrypto“ API .

Jei norite gauti eilutės subtle.digest galite naudoti subtle.digest metodą:

14
13 апр. Atsakymas pateikiamas Kaiido 13 d. 2017-04-13 08:13 '17 8:13 2017-04-13 08:13

Mar10 pavyzdys leido rasti būdą, kaip gauti tokius pačius rezultatus C # ir Javascript for FNV-1a. Jei yra Unicode simbolių, viršutinė dalis yra atmesta dėl rezultatų. Nežinau, kodėl būtų naudinga juos palaikyti, kai jie išjungiami, nes dabar aš tiesiog susiaurinu URL.

C versija

 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“ versija

 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); } 
6
04 мая '15 в 21:58 2015-05-04 21:58 atsakymą djabraham pateikė gegužės 04-15 d. 21:58 2015-05-04 21:58

Čia yra paprastas, gerai paskirstytas 53 bitų maišelis. Tai gana greitas ir yra žymiai mažesnis susidūrimo greitis, palyginti su 32 bitų maišymu.

 var cyrb53 = function(str, seed = 0) { var h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed; for (var 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); }; 

Jis naudoja metodus, panašius į xxHash / MurmurHash, bet ne taip atsargiai. Pasiekiama lavina (ne griežta), todėl nedideli pakeitimai įvestyje turi didelius pokyčius produkcijos atžvilgiu, o tai leidžia atsitiktinai:

 0xc2ba782c97901 = cyrb53("a") 0xeda5bc254d2bf = cyrb53("b") 0xe64cc3b748385 = cyrb53("revenge") 0xd85148d13f93a = cyrb53("revenue") 

Taip pat galite pateikti sėklą alternatyviems srautams, turintiems tą patį įvestį:

 0xee5e6598ccd5c = cyrb53("revenue", 1) 0x72e2831253862 = cyrb53("revenue", 2) 0x0de31708e6ab7 = cyrb53("revenue", 3) 

Techniškai tai yra 64 bitų maišos, tačiau „JavaScript“ yra tik 53 bitų sveikieji skaičiai. Visus 64 bitus vis dar galima naudoti pakeitus šešioliktainės eilutės arba masyvo grąžinimo eilutę:

 return (h2>>>0).toString(16).padStart(8,0)+(h1>>>0).toString(16).padStart(8,0); // or return [h2>>>0, h1>>>0]; 

Esmė yra ta, kad šešioliktainės eilutės kūrimas tampa našumo kliūtimi, o masyvui reikia dviejų palyginimo operatorių vietoj vieno, kuris nėra toks patogus.


Ir tik linksmam, čia yra 32 bitų maišelis „Oneliner“, kuris vis dar viršija FNV / DJB2 / SMDB:

 ash=s=>{for(var i=0,h=1;i<s.length;)h=Math.imul(h^s.charCodeAt(i++),951274213);return(h^h>>>9)>>>0} 
5
04 сент. Atsakymas yra suteiktas bryc 04 sep . 2018-09-04 20:39 '18, 8:39 pm 2018-09-04 20:39

Man reikėjo panašios funkcijos (bet skirtingos), kad būtų sukurtas unikalus identifikatorius pagal naudotojo vardą ir dabartinį laiką. Taigi:

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

Gamina:

 2DVFXJGEKL 6IZPAKFQFL ORGOENVMG ... etc 

redaguoti 2015 m. birželio mėn. naujam kodui naudoju shortid: https://www.npmjs.com/package/shortid

4
31 мая '13 в 3:06 2013-05-31 03:06 atsakymas pateikiamas jcollum gegužės 31 d. 13:06 2013-05-31 03:06

Mano greitas (labai ilgas) vieno linijinio laivo pagrindas, pagrįstas FNV Multiply+Xor metodu:

 my_string.split('').map(v=>v.charCodeAt(0)).reduce((a,v)=>a+((a<<7)+(a<<3))^v).toString(16); 
3
03 дек. Atsakymą pateikė John Smith. 2017-12-03 13:02 '17 at 13:02 2017-12-03 13:02

Greitas ir glaustas, kuris buvo pritaikytas iš čia :

 String.prototype.hashCode = function() { var hash = 5381, i = this.length while(i) hash = (hash * 33) ^ this.charCodeAt(--i) return hash >>> 0; } 
3
20 янв. atsakymas, kurį pateikė soulmachine Jan 20 2017-01-20 03:11 '17 at 3:11 2017-01-20 03:11

Sujungiau du sprendimus (esmiralha ir lordvlad naudotojus), kad gautumėte funkciją, kuri turėtų būti greitesnė naršyklėms, palaikančioms js funkciją sumažinti () ir vis dar suderinama su senomis naršyklėmis:

 String.prototype.hashCode = function() { if (Array.prototype.reduce) { return this.split("").reduce(function(a,b){a=((a<<5)-a)+b.charCodeAt(0);return a } 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; } }; 

Pavyzdys:

 my_string = 'xyz'; my_string.hashCode(); 
2
29 апр. atsakymą pateikė Frank balandžio 29 d. 2015-04-29 14:07 '15 - 14:07 2015-04-29 14:07

Jei norite išvengti susidūrimų, galite naudoti saugų maišą , pvz., SHA-256 . Yra keletas „JavaScript SHA-256“ diegimų.

Aš parašiau testus, kad galėčiau palyginti keletą maišos realizacijų, žr. Https://github.com/brillout/test-javascript-hash-implementations .

Arba eikite į http://brillout.github.io/test-javascript-hash-implementations/, kad atliktumėte testus.

2
22 июля '15 в 22:26 2015-07-22 22:26 atsakymas pateikiamas brillout, liepos 22 d., 15 val. 22:26 2015-07-22 22:26

Aš nuėjau į paprastą char kodų konvertavimą, konvertuotą į heksadecimines eilutes. Tai reiškia santykinai siaurą tikslą, ty paprastą trumpos eilutės (pvz., Antraštių, žymių), kurie turi būti keičiami su serverio pusėje, vaizdą, kuris dėl nereikšmingų priežasčių negali lengvai įgyvendinti gauto „Java“ prievado hashCode. Akivaizdu, kad nėra saugumo programos.

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

Tai galima padaryti glaustesnę ir naršyklei atsparesnę su „Underscore“. Pavyzdys:

 "Lorem Ipsum".hash() "4c6f72656d20497073756d" 

Darau prielaidą, kad jei norėtumėte naudoti griežtesnes eilutes tokiu pačiu būdu, galite tiesiog sumažinti char kodus ir ištaisyti bendrą sumą, o ne sujungti atskirus simbolius kartu:

 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" 

Žinoma, yra didesnė rizika susidurti su šiuo metodu, nors jūs galite žaisti su aritmetiniu sumažinimu, bet norėjote įvairinti ir pailginti maišą.

1
06 мая '15 в 17:16 2015-05-06 17:16 atsakymas duotas swornabsent gegužės 06 '15 , 17:16 2015-05-06 17:16

Šiuo sprendimu galime nurodyti simbolių rinkinį, kad būtų išvengta kai kurių problemų, kai vertės saugomos arba perkeliamos tarp taikomųjų programų lygių, pavyzdžiui: Kai gauta eilutė (hash) atlieka procentinį kodavimą ir ši eilutė siunčiama valdytojui naudojant GET metodą iš pateikimo sluoksnio.

 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 } 
1
17 сент. Atsakymą pateikė Cassio Seffrin 17 sep . 2016-09-17 21:03 '16 at 21:03 2016-09-17 21:03

Šiek tiek supaprastinta @esmiralha atsakymo versija.

Šioje versijoje nepaisau Stringo, nes tai gali sukelti tam tikrą nepageidaujamą elgesį.

 function hashCode(str) { var hash = 0; for (var i = 0; i < str.length; i++) { hash = ~~(((hash << 5) - hash) + str.charCodeAt(i)); } return hash; } 
1
17 февр. Atsakymas pateikiamas crazy2be 17 vasario mėn. 2016-02-17 06:24 '16 at 6:24 am 2016-02-17 06:24

Aš šiek tiek vėluojau partijai, bet jūs galite naudoti šį modulį: kriptą :

 const crypto = require('crypto'); const SALT = '$ome$alt'; function generateHash(pass) { return crypto.createHmac('sha256', SALT) .update(pass) .digest('hex'); } 

Šios funkcijos rezultatas visada yra 64 simboliai; kažkas panašaus į tai: "aa54e7563b1964037849528e7ba068eb7767b1fab74a8d80fe300828b996714a"

0
23 авг. atsakymą pateikė Frismaury 23 rug . 2018-08-23 15:27 '18, 15:27 2018-08-23 15:27

Kiti klausimai apie „ žymes arba užduoti klausimą