zoukankan      html  css  js  c++  java
  • 长篇小说关键字瞬间过滤

    提到关键字搜索,首先联想到的无非就是使用一些indexOf,replace之类的字符函数,最多加上一些正则表达式而已.实现起来虽然很简单,但是这背后的效率问题可曾仔细考虑过?例如论坛中的关键字过滤,一般情况下需过滤的关键字数量及检测的文本长度都不大,所以这一瞬间的过程没有太多值得关注的地方。但若关键字数量不在是屈指可数,而是有成千上万, 并且待检测的文本也是一长篇大论,结果可不再是那么乐观了。大家都知道,每多一个关键字,就要增加一次全文的检索,最终花费的时间将远远超出可接受的范围内。

    废话不多说。直接上代码第一种是用正则写的,演示链接:http://zpf92.github.io/build/test.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>关键词过滤</title>
    </head>
    <style type="text/css">
        *{
            padding: 0;
            margin: 0;
        }
        body{
            text-align: center;
            font-size:14px;
        }
        textarea,#content{
            background: #EEE;
            border: #999 solid 1px;
            display: block;
            margin: 0 auto;
            width: 95%;
        }
        #t1{
            height: 100px;
        }
        #t2,#content{
            height: 400px;
            text-align: left;
        }
        #content{
            overflow: auto;
            font-size:15px;
            display: none;
        }
        #content>span{
            color: red;
        }
        p{
            color: red;
            font-size: 18px;
            margin-top: 10px;
        }
        #time{
            color: lightgreen;
        }
    </style>
    <body>
        <h2>请输入关键字,中间用;隔开^_^<span>(<i style="color: red;" id="count1">0</i>个)</span></h2>
        <textarea id="t1"></textarea>
        <h2>内容<span>(<i style="color: red;" id="count2">0</i>字)</span></h2>
        <textarea id="t2"></textarea>
        <div id="content"></div>
        <input type="button" name="" id="btn" value="过滤"/>
        <input type="button"  id="reset" value="重置"/></br>
        <p>搜索用时 : <span id="time">0</span> ms</p>
        <script type="text/javascript">
            function $(id){
                return document.getElementById(id);
            }
    
            //获取元素
            var oBtn = $('btn'),
                oT1 = $('t1'),
                oT2 = $('t2'),
                oC1 = $('count1'),
                oC2 = $('count2'),
                oReset = $('reset'),
                oContent = $('content'),
                nTime = $('time'),
                bOk = false,
                reg;
    
            document.addEventListener('click',openTxt,false);
            function openTxt(){
                window.open('http://zpf92.github.io/build/source.txt','blank');
                document.removeEventListener('click',openTxt,false);
            }
            //去除重复的关键字
            function remove(arr){
                var arr2 = [];
                for(var i=0;i<arr.length;i++){
                    var result='';
                    if((!findInArr(arr2,arr[i]))&&arr[i]){
                        for(var j=0;j<arr[i].length;j++){
                            if(isNaN(arr[i].charAt(j))){
                                result+='\'+arr[i].charAt(j);
                            }else{
                                result+=arr[i].charAt(j);
                            }
                        }
                        arr2.push(result);
                    }
                }
                //console.log(arr2);
                reg=new RegExp(arr2.join('|'),'g');
                return arr2.length;
            }
            function findInArr(arr,item){
                for(var i=0;i<arr.length;i++){
                    if(arr[i]===item){
                        return true;
                    }
                }
                return false;
            }
    
            //获取关键字总个数
            oT1.addEventListener('input',function(){
                var value = this.value,
                    n;
                if(!this.value){
                    n = 0;
                }else{
                    //考虑用户输入了重复的关键字
                    n = remove(value.split(';'));
                }    
                oC1.innerHTML = n;
                //console.log(reg);
                bOk = true;
            },false);
    
            //获取内容的字数
            oT2.addEventListener('input',function(){
                oC2.innerHTML = this.value?this.value.length:0;
                bOk = true;
            },false);
    
    
            //点击过滤关键字
            oBtn.addEventListener('click',function(){
                //判断用户是否输入关键字或者内容
                if(oT1.value===''&&oT2.value===''){
                    alert('亲,您两个都没输入,我怎么过滤 ^_^');
                    return;
                }else if(oT1.value===''){
                    alert('亲,您没输入关键字,我怎么过滤 ^_^');
                    return;
                }else if(oT2.value===''){
                    alert('亲,您没输入内容,我怎么过滤 ^_^');
                     return;
                }
    
                this.disabled = true;
                oReset.disabled = false;
                oT1.disabled = true;
    
                //var time=new Date().getTime();
                var time=performance.now();
                oContent.innerHTML = oT2.value.replace(reg,function(str){
                    return '<span>'+str+'</span>';
                });
                //nTime.innerHTML=new Date().getTime()-time;
                nTime.innerHTML=(performance.now()-time).toFixed(3);
                oContent.style.display = 'block';
                oT2.style.display = 'none';
            },false);
            oReset.addEventListener('click',function(){
                this.disabled = true;
                oBtn.disabled = false;
                oT1.disabled = false;
                oContent.style.display = 'none';
                oT2.style.display = 'block';
            },false);
        </script>
    </body>
    </html>

    这种是我自己写的,正则每次都是重头开始找而且着了很多次,所以对于一个百万字数的小说关键字过滤耗时太长,下面请大家看下面的代码:

    演示链接  http://zpf92.github.io/build/test3.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    <style type="text/css">
        *{
            padding: 0;
            margin: 0;
        }
        body{
            text-align: center;
            font-size:14px;
        }
        textarea,#content{
            background: #EEE;
            border: #999 solid 1px;
            display: block;
            margin: 0 auto;
            width: 95%;
        }
        #t1{
            height: 100px;
        }
        #t2,#content{
            height: 400px;
            text-align: left;
        }
        #content{
            overflow: auto;
            font-size:15px;
            display: none;
        }
        #content>span{
            color: red;
        }
        p{
            color: red;
            font-size: 18px;
            margin-top: 10px;
        }
        #time{
            color: lightgreen;
        }
    </style>
    <body>
        <h2>关键字<span>(<i style="color: red;" id="count1">0</i>个)</span></h2>
        <textarea id="t1"></textarea>
        <h2>内容<span>(<i style="color: red;" id="count2">0</i>字)</span></h2>
        <textarea id="t2"></textarea>
        <div id="content"></div>
        <input type="button" name="" id="btn" value="过滤"/>
        <input type="button"  id="reset" value="重置"/></br>
        <p>搜索用时 : <span id="time">0</span> ms</p>
        <script type="text/javascript">
            function $(id){
                return document.getElementById(id);
            }
    
            //获取元素
            var oBtn = $('btn'),
                oT1 = $('t1'),
                oT2 = $('t2'),
                oC1 = $('count1'),
                oC2 = $('count2'),
                oReset = $('reset'),
                oContent = $('content'),
                nTime = $('time'),
                bOk = false;
    
    
            document.addEventListener('click',openTxt,false);
            function openTxt(){
                window.open('http://zpf92.github.io/build/source.txt','blank');
                document.removeEventListener('click',openTxt,false);
            }
            //去除重复的关键字
            function remove(arr){
                var arr2 = [];
                for(var i=0;i<arr.length;i++){
                    if(!findInArr(arr2,arr[i])){
                        arr2.push(arr[i]);
                    }
                }
                return arr2.length;
            }
            function findInArr(arr,item){
                for(var i=0;i<arr.length;i++){
                    if(arr[i]===item){
                        return true;
                    }
                }
                return false;
            }
    
            //获取关键字总个数
            oT1.addEventListener('input',function(){
                var value = this.value,
                    n;
                if(!this.value){
                    n = 0;
                }else{
                    //考虑用户输入了重复的关键字
                    n = remove(value.split(';'));
                }    
                oC1.innerHTML = n;
                bOk = true;
            },false);
    
            //获取内容的字数
            oT2.addEventListener('input',function(){
                oC2.innerHTML = this.value?this.value.length:0;
            },false);
    
    
            //点击过滤关键字
            oBtn.addEventListener('click',function(){
                //判断用户是否输入关键字或者内容
                if(oT1.value===''&&oT2.value===''){
                    alert('亲,您两个都没输入,我怎么过滤 ^_^');
                    return;
                }else if(oT1.value===''){
                    alert('亲,您没输入关键字,我怎么过滤 ^_^');
                    return;
                }else if(oT2.value===''){
                    alert('亲,您没输入内容,我怎么过滤 ^_^');
                     return;
                }
    
                var enterValue = oT2.value;
    
                //用于存储输出的内容
                var html=[];
                //用于标记不是关键字的位置
                var index=0;
    
                this.disabled = true;
                oReset.disabled = false;
    
                if(bOk){
                    makeTree(oT1.value);
                    bOk = false;
                }
    
                //开始搜索
                var time = performance.now();
                var arrMath = search(oT2.value);
                //显示搜索用时
                nTime.innerHTML = (performance.now()-time).toFixed(3);
    
                for(var i=0;i<arrMath.length;i+=2){
                    html.push(enterValue.substring(index,arrMath[i]),
                        '<span>',
                        enterValue.substring(arrMath[i],index=arrMath[i+1]),
                        '</span>'
                    );
                }
                //防止尾部漏掉
                html.push(enterValue.substring(index));
                oContent.innerHTML = html.join('');
                oContent.style.display = 'block';
                oT2.style.display = 'none';
            },false);
    
            //重新设置
            oReset.addEventListener('click',function(){
                this.disabled = true;
                oBtn.disabled = false;
                oT1.disabled = false;
                oContent.style.display = 'none';
                oT2.style.display = 'block';
            },false);
    
            var root;
            //将关键字生成一棵树
            function makeTree(sValue){
                var arr = sValue.split('');
                var cur = root = {};
                for(var i=0;i<arr.length;i++){
                    var key = arr[i];
                    if(key===';'){
                        cur.end = true;
                        cur = root;
                        continue;
                    }
                    if(key in cur){
                        cur = cur[key];
                    }else{
                        cur = cur[key] = {};
                    }
                }
                cur.end=true;
            }
            function search(sValue){
                var n=sValue.length;
                var cur;
                var arrMath=[];
                var i=0,p,v;
                while(i<n){
                    cur = root;
                    p = i;
                    v = 0;
                    for(;;){
                        if(!(cur=cur[sValue.charAt(p++)])){
                            i++;
                            break;
                        }
                        if(cur.end){
                            v = p;
                        }
                    }
                    if(v){
                        arrMath.push(i-1,v);
                        i = v;
                    }
                }
                return arrMath;
            }
        </script>
    </body>
    </html>
  • 相关阅读:
    Extjs renderer函数
    孩子,教育,钱
    《新概念英语》的学习方法
    英语,想说爱你爱的太晚
    window.open模拟表单POST提交
    Extjs 解决grid分页bug问题
    Extjs 判断对象是非为null或者为空字符串
    linux shell 删除满足正则表达式的文件
    OpenCV 生成矩形mask
    测试Kaggle kernel commit 是否会删除以前的output
  • 原文地址:https://www.cnblogs.com/tween/p/5262951.html
Copyright © 2011-2022 走看看