我们都使用过主流的搜索引擎,谷歌、 bing,当然还有搜狗、百度之类。当你搜索某一关键词时,它会贴心在下拉框补全一些热门关键词,像下图这样:

搜索关键词提示

你点击某一关键词,页面就直接跳转到结果页面,这种显示搜索关键词提示功能,一定程度上节省用户的搜索时间。

能节省时间的东西就有价值,值得我们学习和使用。

但是,在公司内部的很多系统中,搜索框中都没有这个功能。如果你能实现这个功能,那么你的用户在使用时肯定会眼前一亮,顿生好感,领导看到后也会给你点赞。

这个功能实现非常简单,前端每输入一个字符,都去后端查询前辍相同的关键词返回到下拉列表中即可。前端的实现网上一搜一大堆,比如搜索关键字「搜索框自动补全」就有很多结果,这里就不说了。这里主要说下后端如何实现。

如果关键词数量并不大,我们可以使用最简单的字符串匹配算法,如 BF 算法,就是遍历所有关键词,找出前辍和输入的字符串匹配的并返回给前端即可,Python 语言还提供了字符串的 startswith 这种方法,实现起来就更简单了,简单就意味着不容易出错,没有 bug,在关键词少的情况下,可以优先选择这种方法。

如果关键词量较大,就需要考虑性能问题了,前辍树( Trie 树)就是高效解决这种问题的数据结构。先看一下前辍树的图:

trie树

这棵前辍树根节点不存放数据,其他节点保存了 hello,her,hi,how,see,so 等关键词信息,如果查 he 前辍的单词可以很快返回 hello,her。

这种树的子节点数据并不固定,一般的算法教程在实现时都通过固定每个节点的指针数量来降低实现难度,比如使用一个下标与字符一一映射的数组灰存储子节点的指针,如下图所示:

一种实现方式

这种结构效率非常高,但是比较浪费空间,如果关键词有中文或者标点,更是无法复用。

好在 Python 语言有字典这种高效的数据结构,实现起来易如反掌:键可以作为父节点,值作为子节点,值又是一个字典,包含所有的子节点信息,这种字典里又有字典这种嵌套的方式实现的前辍树也叫字典树。先直观的感受下:

{'中': {-1: True, '国': {-1: True, '人': {-1: True}}, '华': {'人': {'民': {'共': {'和': {'国': {-1: True}}}}}}}}

这里 -1 是 True 表示到这里已经是一个完整的候选词了,上述字典树代表以下关键词:

中国

中国人

中华人民共和国

Trie 树的 Python 实现:

前辍树(Trie 树)主要有三个操作,第一个是就是一个将关键词插入到 Trie 树,第二个是在 Trie 树中查询一个关键词,第三个是返回 Trie 树中给定前辍的所有关键词。实现起来并不难,下面是我的一种实现方法:

# 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 开发")

trie.insert("Python web 开发 视频教程")

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 算')))

代码运行结果如下:

False

True

['Python', 'Python 算法', 'Python 算法 源码', 'Python web', 'Python web 开发', 'Python web 开发 视频教程', 'Perl 算法 源码']

['Python web', 'Python web 开发', 'Python web 开发 视频教程']

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

Trie 的时间复杂度

如果要在一组关键词中,频繁地查询某些关键词,用 Trie 树会非常高效。构建 Trie 树的过程,需要扫描所有的关键词,时间复杂度是 O(n)(n 表示所有关键词的长度和)。但是一旦构建成功之后,后续的查询操作会非常高效。

每次查询时,如果要查询的关键词长度是 k,那我们只需要最多比对 k 个节点,就能完成查询操作。跟原本那组关键词的长度和个数没有任何关系。所以说,构建好 Trie 树后,在其中查找关键词的时间复杂度是 O(k),k 表示要查找的关键词的长度。

不想造轮子,学习下 marisa-trie

自己造轮子还要思考,编码,验证,但这是学习提升的最佳方式。如果急于应用没有时间造轮子,至少要学会如何使用轮子,下面的前辍树的轮子是一个日本人写的,大家可以学习应用下。

写在最后

上述只实现了搜索框智能提示的一小步,实际使用中,你可能还会遇到以下问题:

1、如果候选词过多,应该如何选择性的显示哪些关键词呢?

2、如果用户输入错误,如何仍按正确的拼写来显示候选关键词呢?

第一个问题比如好解决,我们可以按搜索的频度或关键词的搜索结果数来为每个关键词自动生成一个权重数,按权重从大到小选择性的显示前 n 条即可。

第二个问题涉及动态规划,大家可以先思考,如果有时间,会再写一篇文章。

其实 Trie 树在自动补全的需求上都可以大显身手,如输入法自动补全功能、IDE 代码编辑器自动补全功能、浏览器网址输入的自动补全功能等。

(完)

欢迎订阅微信公众号 somenzz,和你一起学习 Python。

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

  1. Trie(字典树) : 如何实现搜索引擎的关键词提示功能?

    文章目录 搜索中的关键词提示 Trie树的介绍 Trie树的实现 搜索的关键词提示 Trie树 VS 红黑树.哈希 搜索中的关键词提示 当我们在搜索引擎中进行搜索时,有时仅仅输入了搜索内容的一部分,搜 ...

  2. python字典的存储结构_解决python字典结构内存暴涨问题

    背景:当读取一个key value数据的时候,python的字典结构会造成内存使用扩10倍左右,无可容忍.此文解决这个问题 数据:word2vec训练的结果,word对应400维的词向量.词表共1.6 ...

  3. python字典中找最小值_从包含元组值的字典中查找最小值和最大值

    我有一本名为cdc_year_出生的python字典.在 对于cdc_year_出生,关键是单位(在本例中,单位是一年),值是该单位中的出生人数:print(cdc_year_births) {200 ...

  4. python 字典键值重复_浅谈python字典多键值及重复键值的使用

    在python中使用字典,格式如下: dict={ key1:value1 , key2;value2 ...} 在实际访问字典值时的使用格式如下: dict[key] 多键值 字典的多键值形式如下: ...

  5. python字典按键值排序_在Python中按键或值按升序和降序对字典排序

    python字典按键值排序 Problem Statement: Write a Python program to sort (ascending and descending) a diction ...

  6. python字典常用的操作_说说Python字典以及基本操作?

    公众号新增加了一个栏目,就是每天给大家解答一道Python常见的面试题,反正每天不贪多,一天一题,正好合适,只希望这个面试栏目,给那些正在准备面试的同学,提供一点点帮助! 小猿会从最基础的面试题开始, ...

  7. android搜索框功能实现_巧用 Trie 树,实现搜索引擎关键词提示功能

    来源 | 码海责编 | Carol封图 | CSDN 付费下载于视觉中国我们几乎每天都在用搜索引擎搜索信息,相信大家肯定有注意过这样一个细节:当输入某个字符的时候,搜索引框底下会出现多个推荐词,如下, ...

  8. python字典由什么组成_在Python中,将由关键字对组成的列表添加到字典中最简单的方法是什么?...

    试试这个:data = [] with open('names.dat') as database: for line in database: if line.strip(): # skip bla ...

  9. 如何用我python抓取关键字新闻_用python机器学习实现新闻关键词的抽取

    随着互联网的蓬勃发展,手机移动端和网络的逐渐普及,传播的权利下放到每个公民,"公民新闻"应运而生,每个公民成为记者,都能通过网络发出自己的声音.随着新闻传播门槛的降低,网上的信息愈 ...

最新文章

  1. 在图形化界面中为Ubuntu18.04更新源
  2. Qt字符串与整形转换
  3. eclipse maven Invalid classpath publish/export dependency
  4. 4个常用的awk统计命令
  5. mapreduce 算法_MapReduce算法–了解数据联接第1部分
  6. C++静态数据成员和静态成员函数
  7. linux编辑java文本,linux下的文本编辑器VI的使用命令
  8. 第十章——维护索引(1)——索引碎片
  9. P3371 单源最短路径【模板】 洛谷
  10. 《给你一个团队,你能怎么管?》读书笔记
  11. scala 资源 copy 自知乎
  12. 总结列表显示ListView知识点
  13. Markdown学习指南
  14. python 判断区分字符串是否都是英文/中文
  15. 数据结构 -- 魔王语言解释
  16. 啊哈添柴挑战Java1826. 顺序输出(简单)
  17. 为何要配置环境变量?
  18. Android之高仿QQ6.6.0侧滑效果(背景动画、透明+沉浸式状态栏、渐变效果)
  19. 蓝桥杯 模板Template Part9:PCF8591 ADC/DAC
  20. 用 Appium 自动收取蚂蚁森林能量

热门文章

  1. 移动前端开发经验小结
  2. Java线程与并发编程实践----同步器(Phaser)
  3. C#跑马灯,图片滚动,后台获取图片地址。动态绑定图片,imag显示文字
  4. TYVJ P1069 cowtour 看不懂题意
  5. Python出现SyntaxError: Non-ASCII character '\xe7' in file 错误的解决办法
  6. vs2012 智能提示消失解决办法
  7. Avalon-MM 阿窝龙妹妹应用笔记
  8. SharePoint Conference 2008 - Day 1
  9. legend2---开发常用语句
  10. 约瑟夫环 单向循环链表实现