手把手教你做關鍵詞匹配項目(搜尋引擎)---- 第二十天,教你做第二十天_PHP教程

來源:互聯網
上載者:User

手把手教你做關鍵詞匹配項目(搜尋引擎)---- 第二十天,教你做第二十天


客串:屌絲的坑人表單神器、資料庫那點事兒

物件導向升華:物件導向的認識----新生的初識、物件導向的番外----思想的夢遊篇(1)、物件導向的認識---如何找出類

負載平衡:負載平衡----概念認識篇、負載平衡----實現配置篇(Nginx)

吐槽:有人反饋了這樣的一個資訊,說該文章越到最後越難看懂,跟不上節奏,也有的人說小帥帥的能力怎麼飆的那麼快,是不是我比較蠢。也有的直接看文字,不看代碼,代碼太難懂了。

其實我這幾天也一直在思考這個問題,所以沒辦法就去開展了一些物件導向的課程,希望對那些跟不上的有些協助。其實說真的,讀者不反饋的話,我只好按照我認為的小帥帥去開展課程了。

第二十天

起點:手把手教你做關鍵詞匹配項目(搜尋引擎)---- 第一天

回顧:手把手教你做關鍵詞匹配項目(搜尋引擎)---- 第十九天

話說小帥帥為瞭解決那個分詞演算法寫出了初版,他拿給於老大看的時候,被要求重寫了。

原因有以下幾點:

1. 如何測試,測試資料呢?

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

3. 連衣裙xxl裙連衣裙這種 有重複片語怎麼辦?

小帥帥拿著這些問題,開始重構。

首先他發現了這點,中文、英文和中英文的判斷,以及長度的計算,他把這個寫成了類:

phpclass UTF8 {    /**     * 檢測是否utf8     * @param $char     * @return bool     */    public static function is($char){        return (preg_match("/^([".chr(228)."-".chr(233)."]{1}[".chr(128)."-".chr(191)."]{1}[".chr(128)."-".chr(191)."]{1}){1}/",$char) ||            preg_match("/([".chr(228)."-".chr(233)."]{1}[".chr(128)."-".chr(191)."]{1}[".chr(128)."-".chr(191)."]{1}){1}$/",$char) ||            preg_match("/([".chr(228)."-".chr(233)."]{1}[".chr(128)."-".chr(191)."]{1}[".chr(128)."-".chr(191)."]{1}){2,}/",$char));    }    /**     * 計算utf8字的個數     * @param $char     * @return float|int     */    public static function length($char) {        if(self::is($char))            return ceil(strlen($char)/3);        return strlen($char);    }    /**     * 檢測是否為片語     * @param $word     * @return bool     */    public static function isPhrase($word){        if(self::length($word)<=1)            return false;        return true;    }}

小帥帥又考慮到詞典的來源有可能來自多個地方,比如我給的測試資料,這樣不就是可以解決於老大說到無法測試的問題了,小帥帥把詞典的來源抽成了個類,類如下:

phpclass DBSegmentation {    public $cid;    /**     * 擷取類目下分詞的片語資料     * @return array     */    public function transferDictionary(){        $ret = array();        $sql = "select word from category_linklist where cid='$this->cid'";        $words = DB::makeArray($sql);        foreach($words as $strWords){            $words = explode(",",$strWords);            foreach($words as $word){                if(UTF8::isPhrase($word)){                    $ret[] = $word;                }            }        }        return $ret;    }} class TestSegmentation {        public function transferDictionary(){        $words = array(            "連衣裙,連衣",            "XXL,xxl,加大,加大碼",            "X碼,中碼",            "外套,衣,衣服,外衣,上衣",            "女款,女士,女生,女性"        );        $ret = array();        foreach($words as $strWords){            $words = explode(",",$strWords);            foreach($words as $word){                if(UTF8::isPhrase($word)){                    $ret[] = $word;                }            }        }        return $ret;    }}

那麼Splitter 就專心分詞把,代碼如下:

class Splitter {    public $keyword;    private $dictionary = array();    public function setDictionary($dictionary = array()){        usort($dictionary,function($a,$b){            return (UTF8::length($a)>UTF8::length($b))?1:-1;        });        $this->dictionary = $dictionary;    }    public function getDictionary(){        return $this->dictionary;    }    /**     * 把關鍵詞拆分成片語或者單詞     * @return KeywordEntity $keywordEntity     */    public function split(){        $remainKeyword = $this->keyword;        $keywordEntity = new KeywordEntity($this->keyword);        foreach($this->dictionary as $phrase){            $matchTimes = preg_match_all("/$phrase/",$remainKeyword,$matches);            if($matchTimes>0){                $keywordEntity->addElement($phrase,$matchTimes);                $remainKeyword = str_replace($phrase,"::",$remainKeyword);            }        }        $remainKeywords = explode("::",$remainKeyword);        foreach($remainKeywords as $splitWord){            if(!empty($splitWord)){                $keywordEntity->addElement($splitWord);            }        }        return $keywordEntity;    }}class KeywordEntity {    public $keyword;    public $elements = array();    public function __construct($keyword){        $this->keyword = $keyword;    }    public function addElement($word,$times=1){        if(isset($this->elements[$word])){            $this->elements[$word]->times += $times;        }else            $this->elements[] = new KeywordElement($word,$times);    }    /**     * @desc 計算UTF8字串權重     * @param string $word     * @return float     */    public function calculateWeight($word)    {        $element = $this->elements[$word];        return ROUND(strlen($element->word)*$element->times / strlen($this->keyword), 3);    }}class KeywordElement {    public $word;    public $times;    public function __construct($word,$times){        $this->word = $word;        $this->times = $times;    }}

他把算權重的也丟給了一個類專門去處理。

小帥帥寫完之後,也順手寫了測試執行個體:

php$segmentation = new TestSegmentation();$splitter = new Splitter();$splitter->setDictionary($segmentation->transferDictionary());$splitter->keyword = "連衣裙xxl裙連衣裙";$keywordEntity = $splitter->split();var_dump($keywordEntity);

這樣就算你的演算法怎麼改,它也能從容面對了。

小帥帥理解了這個,當你覺得類做的事情太多的時候,可以考慮下單一職責原則。

單一職責原則:一個類,只有一個引起它變化的原因。應該只有一個職責。每一個職責都是變化的一個軸線,如果一個類有一個以上的職責,這些職責就耦合在了一起。這會導致脆弱的設計。當一個職責發生變化時,可能會影響其它的職責。另外,多個職責耦合在一起,會影響複用性。例如:要實現邏輯和介面的分離。【來自百度百科】

當於老大提到是不是有其他分詞演算法的時候,我們能不能拿來用,小帥帥很高興,因為現在它的代碼是多麼美好。

小帥帥如何玩轉第三方分詞擴充,請繼續關注下回分解:手把手教你做關鍵詞匹配項目(搜尋引擎)---- 第二十一天




http://www.bkjia.com/PHPjc/873919.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/873919.htmlTechArticle手把手教你做關鍵詞匹配項目(搜尋引擎)---- 第二十天,教你做第二十天 客串:屌絲的坑人表單神器、資料庫那點事兒 物件導向升華:面...

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.