假设你需要在前端展示 5000 条甚至更多的数据,每一条数据的数据结构是一个对象,里面有各种各样的属性。每个属性的值又可以是基本类型,对象,甚至数组。这里的对象或者数组内部的元素又可以继续包含对象或者数组并且允许无限嵌套下去。比如
{ "name": { "firstName": "yi", "lastName": "li" }, "age": 23, "roles": ['developer', 'admin'], "projects": [{ "name": "demo", "repo": "" }]
}
页面上提供一个搜索框,用户通过输入搜索的内容可以找到包含这个内容的数据。注意,只要任意数据对象的任意属性值 (比如在上面的数据结构中,只要 name
, age
, roles
任何一个属性的值)包含这个关键词即可。如果属性值是数组或者对象,那么数组的元素或者对象的值继续对输入内容进行匹配检测,并递归的检测下去,只要有命中,便算该数据匹配
如何设计这个功能,让搜索功能尽可能的快?
解决思路
如果你稍有程序员的敏感度,此时你的脑海里应该有两个念头:
- 遍历以及深度优先遍历是最直接的方式
- 如果要求够快的话遍历我就输了
的确,遍历是最简单但也是最慢的。所以通常的优化方法之一是通过空间换取时间;而另一个方法……稍后再引出。
这里我们尝试通过建立字典树(Trie)来优化搜索。
如果你还不了解什么是字典树,下面做简单的介绍:假设我们有一个简单的对象,键值的对应关系如下:
我们根据「键」的字母出现顺次构建出一棵树出来,叶子节点值即有可能是某个「键」的值
那么此时无论用户想访问任何属性的值,只要从树的根节点出发,依据属性字母出现的顺序访问树的叶子节点,即可得到该属性的值。比如当我们想访问tea
时:
但是在我们需要解决的场景中,我们不需要关心「属性」,我们只关心「值」是否匹配上搜索的内容。所以我们只需要对「值」建立字典树。
假设有以下