搜索
首页php教程php手册手把手教你做关键词匹配项目(搜索引擎)---- 第二十天,教你做第二十天

手把手教你做关键词匹配项目(搜索引擎)---- 第二十天,教你做第二十天

客串:屌丝的坑人表单神器、数据库那点事儿

面向对象升华:面向对象的认识----新生的初识、面向对象的番外----思想的梦游篇(1)、面向对象的认识---如何找出类

负载均衡:负载均衡----概念认识篇、负载均衡----实现配置篇(Nginx)

吐槽:有人反馈了这样的一个信息,说该文章越到最后越难看懂,跟不上节奏,也有的人说小帅帅的能力怎么飙的那么快,是不是我比较蠢。也有的直接看文字,不看代码,代码太难懂了。

其实我这几天也一直在思考这个问题,所以没办法就去开展了一些面向对象的课程,希望对那些跟不上的有些帮助。其实说真的,读者不反馈的话,我只好按照我认为的小帅帅去开展课程了。

 

第二十天

起点:手把手教你做关键词匹配项目(搜索引擎)---- 第一天

回顾:手把手教你做关键词匹配项目(搜索引擎)---- 第十九天

话说小帅帅为了解决那个分词算法写出了初版,他拿给于老大看的时候,被要求重写了。

原因有以下几点:

    1. 如何测试,测试数据呢?

    2. Splitter是不是做了太多事情?

    3. 连衣裙xxl裙连衣裙这种 有重复词组怎么办?

小帅帅拿着这些问题,开始重构。

首先他发现了这点,中文、英文和中英文的判断,以及长度的计算,他把这个写成了类:

<?<span>php

</span><span>class</span><span> UTF8 {

    </span><span>/*</span><span>*
     * 检测是否utf8
     * @param $char
     * @return bool
     </span><span>*/</span>
    <span>public</span> <span>static</span> <span>function</span> is(<span>$char</span><span>){
        </span><span>return</span> (<span>preg_match</span>("/^([".<span>chr</span>(228)."-".<span>chr</span>(233)."]{1}[".<span>chr</span>(128)."-".<span>chr</span>(191)."]{1}[".<span>chr</span>(128)."-".<span>chr</span>(191)."]{1}){1}/",<span>$char</span>) ||
            <span>preg_match</span>("/([".<span>chr</span>(228)."-".<span>chr</span>(233)."]{1}[".<span>chr</span>(128)."-".<span>chr</span>(191)."]{1}[".<span>chr</span>(128)."-".<span>chr</span>(191)."]{1}){1}$/",<span>$char</span>) ||
            <span>preg_match</span>("/([".<span>chr</span>(228)."-".<span>chr</span>(233)."]{1}[".<span>chr</span>(128)."-".<span>chr</span>(191)."]{1}[".<span>chr</span>(128)."-".<span>chr</span>(191)."]{1}){2,}/",<span>$char</span><span>));
    }

    </span><span>/*</span><span>*
     * 计算utf8字的个数
     * @param $char
     * @return float|int
     </span><span>*/</span>
    <span>public</span> <span>static</span> <span>function</span> length(<span>$char</span><span>) {

        </span><span>if</span>(self::is(<span>$char</span><span>))
            </span><span>return</span> <span>ceil</span>(<span>strlen</span>(<span>$char</span>)/3<span>);
        </span><span>return</span> <span>strlen</span>(<span>$char</span><span>);
    }

    </span><span>/*</span><span>*
     * 检测是否为词组
     * @param $word
     * @return bool
     </span><span>*/</span>
    <span>public</span> <span>static</span> <span>function</span> isPhrase(<span>$word</span><span>){

        </span><span>if</span>(self::length(<span>$word</span>)<=1<span>)
            </span><span>return</span> <span>false</span><span>;
        </span><span>return</span> <span>true</span><span>;
    }

}</span>

小帅帅又考虑到词典的来源有可能来自多个地方,比如我给的测试数据,这样不就是可以解决于老大说到无法测试的问题了,小帅帅把词典的来源抽成了个类,类如下:

<?<span>php

</span><span>class</span><span> DBSegmentation {

    </span><span>public</span> <span>$cid</span><span>;

    </span><span>/*</span><span>*
     * 获取类目下分词的词组数据
     * @return array
     </span><span>*/</span>
    <span>public</span> <span>function</span><span> transferDictionary(){
        </span><span>$ret</span> = <span>array</span><span>();
        </span><span>$sql</span> = "select word from category_linklist where cid='<span>$this</span>->cid'"<span>;
        </span><span>$words</span> = DB::makeArray(<span>$sql</span><span>);
        </span><span>foreach</span>(<span>$words</span> <span>as</span> <span>$strWords</span><span>){
            </span><span>$words</span> = <span>explode</span>(",",<span>$strWords</span><span>);

            </span><span>foreach</span>(<span>$words</span> <span>as</span> <span>$word</span><span>){
                </span><span>if</span>(UTF8::isPhrase(<span>$word</span><span>)){
                    </span><span>$ret</span>[] = <span>$word</span><span>;
                }
            }
        }
        </span><span>return</span> <span>$ret</span><span>;
    }
} 

</span><span>class</span><span> TestSegmentation {
    
    </span><span>public</span> <span>function</span><span> transferDictionary(){
        </span><span>$words</span> = <span>array</span><span>(
            </span>"连衣裙,连衣",
            "XXL,xxl,加大,加大码",
            "X码,中码",
            "外套,衣,衣服,外衣,上衣",
            "女款,女士,女生,女性"<span>
        );

        </span><span>$ret</span> = <span>array</span><span>();
        </span><span>foreach</span>(<span>$words</span> <span>as</span> <span>$strWords</span><span>){
            </span><span>$words</span> = <span>explode</span>(",",<span>$strWords</span><span>);

            </span><span>foreach</span>(<span>$words</span> <span>as</span> <span>$word</span><span>){
                </span><span>if</span>(UTF8::isPhrase(<span>$word</span><span>)){
                    </span><span>$ret</span>[] = <span>$word</span><span>;
                }
            }
        }
        </span><span>return</span> <span>$ret</span><span>;

    }
}</span>

那么Splitter 就专心分词把,代码如下:

<span>class</span><span> Splitter {

    </span><span>public</span> <span>$keyword</span><span>;
    </span><span>private</span> <span>$dictionary</span> = <span>array</span><span>();

    </span><span>public</span> <span>function</span> setDictionary(<span>$dictionary</span> = <span>array</span><span>()){

        </span><span>usort</span>(<span>$dictionary</span>,<span>function</span>(<span>$a</span>,<span>$b</span><span>){
            </span><span>return</span> (UTF8::length(<span>$a</span>)>UTF8::length(<span>$b</span>))?1:-1<span>;
        });

        </span><span>$this</span>->dictionary = <span>$dictionary</span><span>;
    }

    </span><span>public</span> <span>function</span><span> getDictionary(){
        </span><span>return</span> <span>$this</span>-><span>dictionary;
    }

    </span><span>/*</span><span>*
     * 把关键词拆分成词组或者单词
     * @return KeywordEntity $keywordEntity
     </span><span>*/</span>
    <span>public</span> <span>function</span> <span>split</span><span>(){

        </span><span>$remainKeyword</span> = <span>$this</span>-><span>keyword;

        </span><span>$keywordEntity</span> = <span>new</span> KeywordEntity(<span>$this</span>-><span>keyword);

        </span><span>foreach</span>(<span>$this</span>->dictionary <span>as</span> <span>$phrase</span><span>){

            </span><span>$matchTimes</span> = <span>preg_match_all</span>("/<span>$phrase</span>/",<span>$remainKeyword</span>,<span>$matches</span><span>);
            </span><span>if</span>(<span>$matchTimes</span>>0<span>){
                </span><span>$keywordEntity</span>->addElement(<span>$phrase</span>,<span>$matchTimes</span><span>);

                </span><span>$remainKeyword</span> = <span>str_replace</span>(<span>$phrase</span>,"::",<span>$remainKeyword</span><span>);
            }
        }

        </span><span>$remainKeywords</span> = <span>explode</span>("::",<span>$remainKeyword</span><span>);
        </span><span>foreach</span>(<span>$remainKeywords</span> <span>as</span> <span>$splitWord</span><span>){

            </span><span>if</span>(!<span>empty</span>(<span>$splitWord</span><span>)){
                </span><span>$keywordEntity</span>->addElement(<span>$splitWord</span><span>);
            }
        }

        </span><span>return</span> <span>$keywordEntity</span><span>;

    }

}


</span><span>class</span><span> KeywordEntity {

    </span><span>public</span> <span>$keyword</span><span>;
    </span><span>public</span> <span>$elements</span> = <span>array</span><span>();

    </span><span>public</span> <span>function</span> __construct(<span>$keyword</span><span>){
        </span><span>$this</span>->keyword = <span>$keyword</span><span>;
    }

    </span><span>public</span> <span>function</span> addElement(<span>$word</span>,<span>$times</span>=1<span>){

        </span><span>if</span>(<span>isset</span>(<span>$this</span>->elements[<span>$word</span><span>])){
            </span><span>$this</span>->elements[<span>$word</span>]->times += <span>$times</span><span>;
        }</span><span>else</span>
            <span>$this</span>->elements[] = <span>new</span> KeywordElement(<span>$word</span>,<span>$times</span><span>);
    }

    </span><span>/*</span><span>*
     * @desc 计算UTF8字符串权重
     * @param string $word
     * @return float
     </span><span>*/</span>
    <span>public</span> <span>function</span> calculateWeight(<span>$word</span><span>)
    {
        </span><span>$element</span> = <span>$this</span>->elements[<span>$word</span><span>];
        </span><span>return</span> <span>ROUND</span>(<span>strlen</span>(<span>$element</span>->word)*<span>$element</span>->times / <span>strlen</span>(<span>$this</span>->keyword), 3<span>);
    }
}


</span><span>class</span><span> KeywordElement {
    </span><span>public</span> <span>$word</span><span>;
    </span><span>public</span> <span>$times</span><span>;

    </span><span>public</span> <span>function</span> __construct(<span>$word</span>,<span>$times</span><span>){
        </span><span>$this</span>->word = <span>$word</span><span>;
        </span><span>$this</span>->times = <span>$times</span><span>;
    }
}</span>

他把算权重的也丢给了一个类专门去处理。

小帅帅写完之后,也顺手写了测试实例:

<?<span>php

</span><span>$segmentation</span> = <span>new</span><span> TestSegmentation();

</span><span>$splitter</span> = <span>new</span><span> Splitter();
</span><span>$splitter</span>->setDictionary(<span>$segmentation</span>-><span>transferDictionary());
</span><span>$splitter</span>->keyword = "连衣裙xxl裙连衣裙"<span>;
</span><span>$keywordEntity</span> = <span>$splitter</span>-><span>split</span><span>();

</span><span>var_dump</span>(<span>$keywordEntity</span>);

 

这样就算你的算法怎么改,它也能从容面对了。

 

小帅帅理解了这个,当你觉得类做的事情太多的时候,可以考虑下单一职责原则。

 

单一职责原则:一个类,只有一个引起它变化的原因。应该只有一个职责。每一个职责都是变化的一个轴线,如果一个类有一个以上的职责,这些职责就耦合在了一起。这会导致脆弱的设计。当一个职责发生变化时,可能会影响其它的职责。另外,多个职责耦合在一起,会影响复用性。例如:要实现逻辑和界面的分离。【来自百度百科】

 

当于老大提到是不是有其他分词算法的时候,我们能不能拿来用,小帅帅很高兴,因为现在它的代码是多么美好。

小帅帅如何玩转第三方分词扩展,请继续关注下回分解:手把手教你做关键词匹配项目(搜索引擎)---- 第二十一天

 

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
解释一下explorer.exe进程是什么解释一下explorer.exe进程是什么Feb 18, 2024 pm 12:11 PM

explorer.exe是什么进程在我们使用Windows操作系统的时候,经常会听到一个名词"explorer.exe".那么,你是否好奇这个进程到底是什么?在本文中,我们将详细解释explorer.exe是什么进程以及其功能和作用。首先,explorer.exe是Windows操作系统的一个关键进程,它负责管理和控制Windows资源管理器(Window

r5 5600x最高能带动什么显卡 最新用5600X搭配RX6800XT性能r5 5600x最高能带动什么显卡 最新用5600X搭配RX6800XT性能Feb 25, 2024 am 10:34 AM

10月29日,AMD终于发布了备受用户期待的重磅产品,即基于全新RDNA2架构的RX6000系列游戏显卡。这款显卡与之前推出的基于全新ZEN3架构的锐龙5000系列处理器相辅相成,形成了一个全新的双A组合。这一次的发布不仅使得竞争对手“双英”黯然失色,也对整个DIY硬件圈产生了重大影响。接下来,围绕笔者手中这套AMD锐龙5600X和RX6800XT的组合作为测试例子,来见证下现如今的AMD究竟有多么Yse?首先说说CPU处理器部分,上一代采用ZEN2架构的AMD锐龙3000系列处理器其实已经令用

内存频率和时序哪个对性能影响更大内存频率和时序哪个对性能影响更大Feb 19, 2024 am 08:58 AM

内存是计算机中非常重要的组件之一,它对计算机的性能和稳定性有着重要影响。在选择内存时,人们往往会关注两个重要的参数,即时序和频率。那么,对于内存性能来说,时序和频率哪个更重要呢?首先,我们来了解一下时序和频率的概念。时序指的是内存芯片在接收和处理数据时所需的时间间隔。它通常以CL值(CASLatency)来表示,CL值越小,内存的处理速度越快。而频率则是内

发生0x0000004e错误代表了什么问题发生0x0000004e错误代表了什么问题Feb 18, 2024 pm 01:54 PM

0x0000004e是什么故障在计算机系统中,故障是一个常见的问题。当计算机遇到故障时,系统通常会因为无法正常运行而出现停机、崩溃或者出现错误提示。而在Windows系统中,有一个特定的故障代码0x0000004e,这是一个蓝屏错误代码,表示系统遇到了一个严重的错误。0x0000004e蓝屏错误是由于系统内核或驱动程序问题导致的。这种错误通常会导致计算机系统

教你使用 iOS 17.4「失窃设备保护」新进阶功能教你使用 iOS 17.4「失窃设备保护」新进阶功能Mar 10, 2024 pm 04:34 PM

Apple在周二推出了iOS17.4更新,为iPhone带来了一系列新功能和修复。这次更新包括了全新的表情符号,同时欧盟用户也能够下载其他应用商店。此外,更新还加强了对iPhone安全性的控制,引入了更多的「失窃设备保护」设置选项,为用户提供更多选择和保障。"iOS17.3首次引入了“失窃设备保护”功能,为用户的敏感资料增加了额外的安全保障。当用户不在家等熟悉地点时,该功能要求用户首次输入生物特征信息,并在一小时后再次输入信息才能访问和更改某些数据,如修改AppleID密码或关闭失窃设备保护功能

Microsoft Edge在哪设置显示下载按钮-Microsoft Edge设置显示下载按钮的方法Microsoft Edge在哪设置显示下载按钮-Microsoft Edge设置显示下载按钮的方法Mar 06, 2024 am 11:49 AM

大家知道MicrosoftEdge在哪设置显示下载按钮吗?下文小编就带来了MicrosoftEdge设置显示下载按钮的方法,希望对大家能够有所帮助,一起跟着小编来学习一下吧!第一步:首先打开MicrosoftEdge浏览器,单击右上角【...】标识,如下图所示。第二步:然后在弹出菜单中,单击【设置】,如下图所示。第三步:接着单击界面左侧【外观】,如下图所示。第四步:最后单击【显示下载按钮】右侧按钮,由灰变蓝即可,如下图所示。上面就是小编为大家带来的MicrosoftEdge在哪设置显示下载按钮的

哪些免费的dll修复工具可以使用?哪些免费的dll修复工具可以使用?Feb 19, 2024 pm 08:35 PM

免费的dll修复工具有哪些导语:随着电脑使用的频繁,有时我们可能会遇到一些dll文件损坏或丢失的问题,这会导致某些软件无法正常运行,给用户带来了很大的困扰。幸运的是,市面上有一些免费的dll修复工具可以帮助我们解决这个问题。本文将介绍几款常用的免费dll修复工具,并对其功能和特点进行分析。一、DLL-FilesFixerDLL-FilesFixer是一

专访 OSL Group CEO:交易所也可以“不走寻常路”专访 OSL Group CEO:交易所也可以“不走寻常路”Feb 29, 2024 pm 07:25 PM

整理:Babywhale,ForesightNews目前获得了香港虚拟资产交易所牌照的交易所有两家:OSL和HaskKeyExchange。很多人在不同的Web3媒体平台上会看到HashKeyExchange上线各种代币的消息,而OSL的类似新闻却相对较少。但实际上,OSL正积极进取,只不过它选择了一条似乎与传统交易所不同的发展道路。潘志勇在获得了BGX的投资后,担任了OSL的新董事局主席和首席执行官。OSL此前在公众眼中相对低调,现在面临着转变的压力,潘志勇将如何引领公司走向前景,这将成为一个

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
2 周前By尊渡假赌尊渡假赌尊渡假赌
仓库:如何复兴队友
4 周前By尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒险:如何获得巨型种子
3 周前By尊渡假赌尊渡假赌尊渡假赌

热工具

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

将Eclipse与SAP NetWeaver应用服务器集成。

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

Atom编辑器mac版下载

Atom编辑器mac版下载

最流行的的开源编辑器