ckHash函數類,將字符串映射成數字,同時可以將數字映射成字符串
說明
1、所謂的BitMap就是用一個bit位來標記某個元素所對應的value,而key即是該元素,由於BitMap使用了bit位來存儲數據,因此可以大大節省存儲空間。
2、ckHash函數類適用於做key-value的字符映射關系,利用字符串正則密鑰給定一個值范圍,以及bit長度len,將字符串映射成0-len之間的數字,同時將0-len之間的數字還原成字符串,這樣能使空間的利用率很高,准確度100%(數字和字符一一對應的關系)。
3、最下面包含BitMap算法的實現,字符查詢以及去重
用途:
bitMap算法之ckHash函數類,將字符串映射成數字,同時可以將數字映射成字符串,
用於數據壓縮,加密解密,以及bitMap大數據查詢,去重
作者:caoke
demo測試100%通過
//demo var d=new ckHash("http://www.baidu.com/[1~8dc-].[1~8dcv][1~8dcv]ml") // console.log(d.toString(11)) // console.log(d.toNumber(d.toString(11))) for(var i=0;i< d.length;i++){ const str=d.toString(i); const num=d.toNumber(str) console.log(str) console.log(i,num) }
測試輸出
http://www.baidu.com/1.11ml 0 0 http://www.baidu.com/1.12ml 1 1 http://www.baidu.com/1.13ml 2 2 http://www.baidu.com/1.14ml 3 3 http://www.baidu.com/1.15ml 4 4 http://www.baidu.com/1.16ml 5 5 http://www.baidu.com/1.17ml 6 6 http://www.baidu.com/1.18ml 7 7 http://www.baidu.com/1.1dml 8 8 http://www.baidu.com/1.1cml 9 9 http://www.baidu.com/1.1vml 10 10 http://www.baidu.com/1.21ml 11 11 http://www.baidu.com/1.22ml 12 12 http://www.baidu.com/1.23ml 13 13 http://www.baidu.com/1.24ml 14 14 http://www.baidu.com/1.25ml 15 15 http://www.baidu.com/1.26ml 16 16 http://www.baidu.com/1.27ml 17 17 http://www.baidu.com/1.28ml 18 18 http://www.baidu.com/1.2dml 19 19 http://www.baidu.com/1.2cml 20 20 http://www.baidu.com/1.2vml
此處省略1000行
源碼
/* * ckHash函數類,將字符串映射成數字,同時可以將數字映射成字符串, * 用於數據壓縮,加密解密,以及bitMap大數據查詢,去重 * 作者:caoke * */ class ckHash{ //輸入密鑰 constructor(secretKey){ this.secretKey=secretKey; this.regexp=new RegExp(secretKey.replace(/\[([^\[]+?)\]/g,function (m) { return '('+m.replace(/-/g,'\\-').replace(/~/g,'-')+')' }).replace(/[\\\^\:\.\?\+]/g,'\\$&')); this.lenArr=[]; this.dataArr=[]; secretKey.replace(/\[([^\[]+?)\]/g,(m,p1)=>{ const arr=[]; for(let i=0;i<p1.length;i++){ if(p1[i]==='~'){ arr.push('~') }else{ arr.push(p1[i].charCodeAt(0)); } } let length=0; for(let i=0;i<arr.length;i++){ if(arr[i]==='~'){ length=length+arr[i+1]-arr[i-1]; i++; }else{ length=length+1; } } this.lenArr.push(length) this.dataArr.push(arr) }) this.length=this.lenArr.reduce((x,y)=>x*y) } //將數字映射成字符串 toString(number){ const arr=[]; for(let i=this.lenArr.length-1;i>0;i--){ const n1=number%this.lenArr[i]; arr.unshift(n1) number=Math.floor(number/this.lenArr[i]); } arr.unshift(number) const codeArr=[] for(let i=0;i<arr.length;i++){ const dataArr=this.dataArr[i]; let len= arr[i]; let code; for(let j=0;j<dataArr.length;j++){ if(dataArr[j]==='~'){ if(len<dataArr[j+1]-dataArr[j-1]){ code=dataArr[j-1]+len+1; break; }else{ len=len-(dataArr[j+1]-dataArr[j-1]); j++; } }else if(len===0){ code=dataArr[j] break; }else{ len--; } } codeArr.push(String.fromCharCode(code)) } let index=0; return this.secretKey.replace(/\[([^\[]+?)\]/g,(m,p1)=>{ return codeArr[index++]; }) } //將字符串映射成數字 toNumber(string){ if(this.regexp.test(string)){ const arr=[] string.replace(this.regexp,function (m,p1) { for(let i=1;i<arguments.length-2;i++){ arr.push(arguments[i].charCodeAt(0)) } }); const lenArr=[] for(let i=0;i<arr.length;i++){ const dataArr=this.dataArr[i]; let len= 0; for(let j=0;j<dataArr.length;j++){ if(dataArr[j]===arr[i]){ break; }else if(dataArr[j]==='~'){ if(arr[i]<=dataArr[j+1]&&arr[i]>dataArr[j-1]){ len=len+arr[i]-dataArr[j-1]-1; break; }else{ len=len+dataArr[j+1]-dataArr[j-1]; j++; } }else{ len++; } } lenArr.push(len) } let number=0; let jz=1; for(let i=lenArr.length-1;i>=0;i--){ number=number+jz*lenArr[i]; jz=jz*this.lenArr[i] } return number; }else{ throw string +' 不在匹配范圍內'; } } } //demo var d=new ckHash("http://www.baidu.com/[1~8dc-].[1~8dcv][1~8dcv]ml") // console.log(d.toString(11)) // console.log(d.toNumber(d.toString(11))) for(var i=0;i< d.length;i++){ const str=d.toString(i); const num=d.toNumber(str) console.log(str) console.log(i,num) }
BItMap算法的實現
//BitMap算法,大數據查詢,算法復雜度O(1) class BitMap { constructor(secretKey){ this.hashFunc=new ckHash(secretKey); this.length=this.hashFunc.length this.buffer=Buffer.alloc(this.length); } has(num){ if(typeof num ==='string'){ num=this.toNumber(num); } const n=num>>3; const k=num%8; return (this.buffer[n]&1<<k)!==0 } toString(num){ return this.hashFunc.toString(num); } toNumber(str){ return this.hashFunc.toNumber(str); } set(num){ if(typeof num ==='string'){ num=this.toNumber(num); } const n=num>>3; const k=num%8; this.buffer[n]=this.buffer[n]|(1<<k); } del(num){ if(typeof num ==='string'){ num=this.toNumber(num); } const n=num>>3; const k=num%8; this.buffer[n]=this.buffer[n]&~(1<<k); } } //demo const b=new BitMap('http://www.baidu.com/[1~8dc-].[1~8dcv][1~8dcv]ml') for(var i=0;i< b.length;i++){ const str=b.toString(i); const num=b.toNumber(str); console.log(i,num,str) //設置 b.set(str) } for(var i=0;i< b.length;i++){ const str=b.toString(i); //查詢 console.log(b.has(str),b.has(i)) } console.log(b.buffer)