手把手教你做关键词匹配项目(搜索引擎)---- 第二十天,教你做第二十天
手把手教你做关键词匹配项目(搜索引擎)---- 第二十天,教你做第二十天
客串:屌丝的坑人表单神器、数据库那点事儿
面向对象升华:面向对象的认识----新生的初识、面向对象的番外----思想的梦游篇(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>);
这样就算你的算法怎么改,它也能从容面对了。
小帅帅理解了这个,当你觉得类做的事情太多的时候,可以考虑下单一职责原则。
单一职责原则:一个类,只有一个引起它变化的原因。应该只有一个职责。每一个职责都是变化的一个轴线,如果一个类有一个以上的职责,这些职责就耦合在了一起。这会导致脆弱的设计。当一个职责发生变化时,可能会影响其它的职责。另外,多个职责耦合在一起,会影响复用性。例如:要实现逻辑和界面的分离。【来自百度百科】
当于老大提到是不是有其他分词算法的时候,我们能不能拿来用,小帅帅很高兴,因为现在它的代码是多么美好。
小帅帅如何玩转第三方分词扩展,请继续关注下回分解:手把手教你做关键词匹配项目(搜索引擎)---- 第二十一天

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas



Melaraskan saiz apertur mempunyai kesan penting pada kesan foto Xiaomi Mi 14 Ultra memberikan fleksibiliti yang tidak pernah berlaku sebelum ini dalam pelarasan apertur kamera. Untuk membolehkan semua orang melaraskan apertur dengan lancar dan merealisasikan pelarasan percuma saiz apertur, editor di sini membawakan anda tutorial terperinci tentang cara menetapkan apertur pada Xiaomi Mi 14Ultra. Bagaimana untuk melaraskan apertur pada Xiaomi Mi 14Ultra? Mulakan kamera, tukar kepada "Mod Profesional", dan pilih kamera utama - kanta W. Klik pada apertur, buka dail apertur, A adalah automatik, pilih f/1.9 atau f/4.0 mengikut keperluan.

Teorem terakhir Fermat, akan ditakluki oleh AI? Dan bahagian yang paling bermakna dari keseluruhannya ialah Teorem Terakhir Fermat, yang akan diselesaikan oleh AI, dengan tepat untuk membuktikan bahawa AI tidak berguna. Suatu ketika dahulu, matematik tergolong dalam alam kecerdasan manusia yang tulen kini, wilayah ini dihuraikan dan diinjak oleh algoritma canggih. Imej Teorem Terakhir Fermat ialah teka-teki "terkenal" yang telah membingungkan ahli matematik selama berabad-abad. Ia telah terbukti pada tahun 1993, dan kini ahli matematik mempunyai rancangan besar: untuk mencipta semula bukti menggunakan komputer. Mereka berharap bahawa sebarang ralat logik dalam versi bukti ini boleh disemak oleh komputer. Alamat projek: https://github.com/riccardobrasca/flt

Ce Modifier (CheatEngine) ialah alat pengubahsuaian permainan yang didedikasikan untuk mengubah suai dan menyunting memori permainan Jadi bagaimana untuk menetapkan bahasa Cina dalam CheatEngine Seterusnya, editor akan memberitahu anda bagaimana untuk menetapkan bahasa Cina dalam Ce Modifier. Dalam perisian baharu yang kami muat turun, ia boleh mengelirukan untuk mendapati bahawa antara muka itu bukan dalam bahasa Cina. Walaupun perisian ini tidak dibangunkan di China, terdapat cara untuk menukarnya kepada versi Cina. Masalah ini boleh diselesaikan dengan hanya menggunakan patch Cina. Selepas memuat turun dan memasang perisian CheatEngine (ce modifier), buka lokasi pemasangan dan cari folder bernama bahasa, seperti yang ditunjukkan dalam rajah di bawah

Honor 90GT ialah telefon pintar kos efektif dengan prestasi cemerlang dan pengalaman pengguna yang cemerlang. Walau bagaimanapun, kadangkala kita mungkin menghadapi beberapa masalah, seperti bagaimana untuk mengemas kini Honor MagicOS8.0 pada Honor 90GT? Langkah ini mungkin berbeza untuk telefon mudah alih yang berbeza dan model yang berbeza Jadi, mari kita bincangkan cara meningkatkan sistem dengan betul. Bagaimana untuk mengemas kini Honor MagicOS 8.0 pada Honor 90GT Menurut berita pada 28 Februari, Honor hari ini menolak kemas kini beta awam MagicOS8.0 untuk tiga telefon mudah alihnya 90GT/100/100Pro Nombor versi pakej ialah 8.0.0.106 (C00E106R3P1) 1. . Pastikan Kehormatan anda Bateri 90GT dicas sepenuhnya;

Apple melancarkan kemas kini iOS 17.4 pada hari Selasa, membawakan pelbagai ciri dan pembaikan baharu kepada iPhone. Kemas kini termasuk emoji baharu, dan pengguna EU juga boleh memuat turunnya daripada kedai aplikasi lain. Di samping itu, kemas kini juga mengukuhkan kawalan keselamatan iPhone dan memperkenalkan lebih banyak pilihan tetapan "Perlindungan Peranti Dicuri" untuk menyediakan pengguna dengan lebih banyak pilihan dan perlindungan. "iOS17.3 memperkenalkan fungsi "Perlindungan Peranti Dicuri" buat kali pertama, menambahkan keselamatan tambahan kepada maklumat sensitif pengguna. Apabila pengguna berada jauh dari rumah dan tempat biasa lain, fungsi ini memerlukan pengguna memasukkan maklumat biometrik untuk pertama kali masa, dan selepas satu jam Anda mesti memasukkan maklumat sekali lagi untuk mengakses dan menukar data tertentu, seperti menukar kata laluan Apple ID anda atau mematikan perlindungan peranti yang dicuri.

Berita terkini, lackMagic telah melancarkan kemas kini beta awam 18.5PublicBeta2 bagi perisian penyuntingan video DaVinci Resolve Studio, membawakan sokongan pengekodan AV1 kepada kad grafik AMD Radeon. Selepas mengemas kini kepada versi terkini, pengguna kad grafik AMD akan dapat memanfaatkan pecutan perkakasan untuk pengekodan AV1 dalam DaVinci Resolve Studio. Walaupun pegawai tidak menyatakan seni bina atau model yang disokong, diharapkan semua pengguna kad grafik AMD boleh mencuba ciri ini. Pada 2018, AOMedia mengeluarkan standard pengekodan video baharu AV1 (AOMediaVideoCodec1.0). AV1 dihasilkan oleh beberapa

Projek permainan Metaverse popular yang diasaskan dalam kitaran crypto terakhir sedang mempercepatkan pengembangannya. Pada 4 Mac, PlanetMojo, platform metaverse permainan Web3, mengumumkan beberapa perkembangan penting dalam ekologi permainannya, termasuk pengumuman permainan parkour yang akan datang GoGoMojo, pelancaran musim baharu "Way of War" dalam auto-catur perdana. permainan MojoMelee, dan sambutan siri ETH pertama "WarBannerNFT" yang baharu dilancarkan musim ini dengan kerjasama MagicEden. Selain itu, PlanetMojo juga mendedahkan bahawa mereka merancang untuk melancarkan versi mudah alih Android dan iOS MojoMelee pada akhir tahun ini. Projek ini akan dilancarkan pada penghujung tahun 2021. Selepas hampir dua tahun bekerja keras dalam pasaran beruang, ia akan siap tidak lama lagi.

Jawapan: Ya, Golang menyediakan fungsi yang memudahkan pemprosesan muat naik fail. Butiran: Jenis MultipartFile menyediakan akses kepada metadata dan kandungan fail. Fungsi FormFile mendapat fail tertentu daripada permintaan borang. Fungsi ParseForm dan ParseMultipartForm digunakan untuk menghuraikan data borang dan data borang berbilang bahagian. Menggunakan fungsi ini memudahkan proses pemprosesan fail dan membolehkan pembangun menumpukan pada logik perniagaan.
