日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

python字典实现关键字检索_如何实现搜索框的关键词提示功能

發(fā)布時間:2025/6/17 python 125 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python字典实现关键字检索_如何实现搜索框的关键词提示功能 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

我們都使用過主流的搜索引擎,谷歌、 bing,當(dāng)然還有搜狗、百度之類。當(dāng)你搜索某一關(guān)鍵詞時,它會貼心在下拉框補(bǔ)全一些熱門關(guān)鍵詞,像下圖這樣:

搜索關(guān)鍵詞提示

你點擊某一關(guān)鍵詞,頁面就直接跳轉(zhuǎn)到結(jié)果頁面,這種顯示搜索關(guān)鍵詞提示功能,一定程度上節(jié)省用戶的搜索時間。

能節(jié)省時間的東西就有價值,值得我們學(xué)習(xí)和使用。

但是,在公司內(nèi)部的很多系統(tǒng)中,搜索框中都沒有這個功能。如果你能實現(xiàn)這個功能,那么你的用戶在使用時肯定會眼前一亮,頓生好感,領(lǐng)導(dǎo)看到后也會給你點贊。

這個功能實現(xiàn)非常簡單,前端每輸入一個字符,都去后端查詢前輟相同的關(guān)鍵詞返回到下拉列表中即可。前端的實現(xiàn)網(wǎng)上一搜一大堆,比如搜索關(guān)鍵字「搜索框自動補(bǔ)全」就有很多結(jié)果,這里就不說了。這里主要說下后端如何實現(xiàn)。

如果關(guān)鍵詞數(shù)量并不大,我們可以使用最簡單的字符串匹配算法,如 BF 算法,就是遍歷所有關(guān)鍵詞,找出前輟和輸入的字符串匹配的并返回給前端即可,Python 語言還提供了字符串的 startswith 這種方法,實現(xiàn)起來就更簡單了,簡單就意味著不容易出錯,沒有 bug,在關(guān)鍵詞少的情況下,可以優(yōu)先選擇這種方法。

如果關(guān)鍵詞量較大,就需要考慮性能問題了,前輟樹( Trie 樹)就是高效解決這種問題的數(shù)據(jù)結(jié)構(gòu)。先看一下前輟樹的圖:

trie樹

這棵前輟樹根節(jié)點不存放數(shù)據(jù),其他節(jié)點保存了 hello,her,hi,how,see,so 等關(guān)鍵詞信息,如果查 he 前輟的單詞可以很快返回 hello,her。

這種樹的子節(jié)點數(shù)據(jù)并不固定,一般的算法教程在實現(xiàn)時都通過固定每個節(jié)點的指針數(shù)量來降低實現(xiàn)難度,比如使用一個下標(biāo)與字符一一映射的數(shù)組灰存儲子節(jié)點的指針,如下圖所示:

一種實現(xiàn)方式

這種結(jié)構(gòu)效率非常高,但是比較浪費空間,如果關(guān)鍵詞有中文或者標(biāo)點,更是無法復(fù)用。

好在 Python 語言有字典這種高效的數(shù)據(jù)結(jié)構(gòu),實現(xiàn)起來易如反掌:鍵可以作為父節(jié)點,值作為子節(jié)點,值又是一個字典,包含所有的子節(jié)點信息,這種字典里又有字典這種嵌套的方式實現(xiàn)的前輟樹也叫字典樹。先直觀的感受下:

{'中': {-1: True, '國': {-1: True, '人': {-1: True}}, '華': {'人': {'民': {'共': {'和': {'國': {-1: True}}}}}}}}

這里 -1 是 True 表示到這里已經(jīng)是一個完整的候選詞了,上述字典樹代表以下關(guān)鍵詞:

中國

中國人

中華人民共和國

Trie 樹的 Python 實現(xiàn):

前輟樹(Trie 樹)主要有三個操作,第一個是就是一個將關(guān)鍵詞插入到 Trie 樹,第二個是在 Trie 樹中查詢一個關(guān)鍵詞,第三個是返回 Trie 樹中給定前輟的所有關(guān)鍵詞。實現(xiàn)起來并不難,下面是我的一種實現(xiàn)方法:

# encoding = utf-8

class Trie(object):

def __init__(self):

"""

Initialize your data structure here.

"""

self.root = {}

self.end = -1

def insert(self, word):

"""

Inserts a word into the trie.

:type word: str

:rtype: void

"""

curNode = self.root

for c in word:

if not c in curNode:

curNode[c] = {}

curNode = curNode[c]

curNode[self.end] = True

def search(self, word):

"""

Returns if the word is in the trie.

:type word: str

:rtype: bool

"""

curNode = self.root

for c in word:

if not c in curNode:

return False

curNode = curNode[c]

# Doesn't end here

if not self.end in curNode:

return False

return True

def startsWith(self, prefix):

"""

Returns if there is any word in the trie that starts with the given prefix.

:type prefix: str

:rtype: bool

"""

curNode = self.root

for c in prefix:

if not c in curNode:

return False

curNode = curNode[c]

return True

def get_start(self,prefix):

'''

給出一個前輟,打印出所有匹配的字符串

:param prefix:

:return:

'''

def get_key(pre,pre_node):

result = []

if pre_node.get(self.end):

result.append(pre)

for key in pre_node.keys():

if key != self.end:

result.extend(get_key(pre+key,pre_node.get(key)))

return result

if not self.startsWith(prefix):

return []

else:

node = self.root

for p in prefix:

node = node.get(p)

else:

return get_key(prefix,node)

if __name__ == "__main__":

trie = Trie()

trie.insert("Python")

trie.insert("Python 算法")

trie.insert("Python web")

trie.insert("Python web 開發(fā)")

trie.insert("Python web 開發(fā) 視頻教程")

trie.insert("Python 算法 源碼")

trie.insert("Perl 算法 源碼")

print(trie.search("Perl"))

print(trie.search("Perl 算法 源碼"))

print((trie.get_start('P')))

print((trie.get_start('Python web')))

print((trie.get_start('Python 算')))

print((trie.get_start('P')))

print((trie.get_start('Python web')))

print((trie.get_start('Python 算')))

代碼運行結(jié)果如下:

False

True

['Python', 'Python 算法', 'Python 算法 源碼', 'Python web', 'Python web 開發(fā)', 'Python web 開發(fā) 視頻教程', 'Perl 算法 源碼']

['Python web', 'Python web 開發(fā)', 'Python web 開發(fā) 視頻教程']

['Python 算法', 'Python 算法 源碼']

Trie 的時間復(fù)雜度

如果要在一組關(guān)鍵詞中,頻繁地查詢某些關(guān)鍵詞,用 Trie 樹會非常高效。構(gòu)建 Trie 樹的過程,需要掃描所有的關(guān)鍵詞,時間復(fù)雜度是 O(n)(n 表示所有關(guān)鍵詞的長度和)。但是一旦構(gòu)建成功之后,后續(xù)的查詢操作會非常高效。

每次查詢時,如果要查詢的關(guān)鍵詞長度是 k,那我們只需要最多比對 k 個節(jié)點,就能完成查詢操作。跟原本那組關(guān)鍵詞的長度和個數(shù)沒有任何關(guān)系。所以說,構(gòu)建好 Trie 樹后,在其中查找關(guān)鍵詞的時間復(fù)雜度是 O(k),k 表示要查找的關(guān)鍵詞的長度。

不想造輪子,學(xué)習(xí)下 marisa-trie

自己造輪子還要思考,編碼,驗證,但這是學(xué)習(xí)提升的最佳方式。如果急于應(yīng)用沒有時間造輪子,至少要學(xué)會如何使用輪子,下面的前輟樹的輪子是一個日本人寫的,大家可以學(xué)習(xí)應(yīng)用下。

寫在最后

上述只實現(xiàn)了搜索框智能提示的一小步,實際使用中,你可能還會遇到以下問題:

1、如果候選詞過多,應(yīng)該如何選擇性的顯示哪些關(guān)鍵詞呢?

2、如果用戶輸入錯誤,如何仍按正確的拼寫來顯示候選關(guān)鍵詞呢?

第一個問題比如好解決,我們可以按搜索的頻度或關(guān)鍵詞的搜索結(jié)果數(shù)來為每個關(guān)鍵詞自動生成一個權(quán)重數(shù),按權(quán)重從大到小選擇性的顯示前 n 條即可。

第二個問題涉及動態(tài)規(guī)劃,大家可以先思考,如果有時間,會再寫一篇文章。

其實 Trie 樹在自動補(bǔ)全的需求上都可以大顯身手,如輸入法自動補(bǔ)全功能、IDE 代碼編輯器自動補(bǔ)全功能、瀏覽器網(wǎng)址輸入的自動補(bǔ)全功能等。

(完)

歡迎訂閱微信公眾號 somenzz,和你一起學(xué)習(xí) Python。

總結(jié)

以上是生活随笔為你收集整理的python字典实现关键字检索_如何实现搜索框的关键词提示功能的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。