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)
