bitMap算法将字符串映射成数字,同时可以将数字映射成字符串-javascript

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)

  

  

posted @ 2019-04-30 03:51  无工时代  阅读(3254)  评论(0编辑  收藏  举报