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)