使用 JavaScript 实现简单候选项推荐功能(模糊搜索)

2023-10-27 20:32

本文主要是介绍使用 JavaScript 实现简单候选项推荐功能(模糊搜索),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

http://yujiangshui.com/javascript-levenshtein-distance/

当我们使用 Google 等搜索功能时,会出现与搜索内容有关的候选项。使用 JavaScript 搜索字符串,通常会使用 indexOf 或者 search 函数,但是非常僵硬,只能搜索匹配特定词语。比如使用关键词 今天是星期几 想要检索 今天是星期五 这个内容,就无法实现,虽然它们只有很小的差别。

本文就来介绍一个有趣的算法 编辑距离(Levenshtein Distance),然后用它来实现一个简单的候选项推荐(模糊搜索)功能。

编辑距离(Levenshtein Distance)

简单的说,编辑距离就是把一个字符串修改变成另一个字符串的修改次数。如果修改的次数越小,我们可以简单的认为这两个字符串之间的关系越紧密。比如 今天是星期几 对于 今天是星期五 和 明天是星期五比较,跟 今天是星期五 更加紧密一些,因为前者的编辑距离是 1,后者的编辑距离是 2。

更详细的百度百科已经说的很清楚了,这里不再赘述,主要给出 JavaScript 的实现方法:

按照自然语言表达的算法,我们先需要根据两个字符串的长度创建一个二维表:

function levenshtein(a, b) {var al = a.length + 1;var bl = b.length + 1;var result = [];var temp = 0;// 创建一个二维数组for (var i = 0; i < al; result[i] = [i++]) {}for (var i = 0; i < bl; result[0][i] = i++) {}}

之后就需要遍历这个二位数组,按照如下的规则取得三个值的最小值:

  • 如果最上方的字符等于最左方的字符,则为左上方的数字。否则为左上方的数字 + 1。
  • 左方数字 + 1
  • 上方数字 + 1

需要判断两个值是否相等来决定左上方数字是否 + 1,所以引入 temp 变量。我们可以写出如下遍历代码:

for (i = 1; i < al; i++) {for (var j = 1; j < bl; j++) {// 判断最上方和最左方数字是否相等temp = a[i - 1] == b[j - 1] ? 0 : 1;// result[i - 1][j] + 1 左方数字// result[i][j - 1] + 1 上方数字// result[i - 1][j - 1] + temp 左上方数字result[i][j] = Math.min(result[i - 1][j] + 1, result[i][j - 1] + 1, result[i - 1][j - 1] + temp);}
}

最后将二维数组最后一个值返回,该值就是编辑距离:

return result[i-1][j-1];

这个函数就完成了:

function levenshtein(a, b) {var al = a.length + 1;var bl = b.length + 1;var result = [];var temp = 0;// 创建一个二维数组for (var i = 0; i < al; result[i] = [i++]) {}for (var i = 0; i < bl; result[0][i] = i++) {}		for (i = 1; i < al; i++) {for (var j = 1; j < bl; j++) {// 判断最上方和最左方数字是否相等temp = a[i - 1] == b[j - 1] ? 0 : 1;// result[i - 1][j] + 1 左方数字// result[i][j - 1] + 1 上方数字// result[i - 1][j - 1] + temp 左上方数字result[i][j] = Math.min(result[i - 1][j] + 1, result[i][j - 1] + 1, result[i - 1][j - 1] + temp);}}return result[i-1][j-1];}

实际应用

那么我们现在就来实现一个简单的搜索功能。

大体思路就是将数据与要搜索的字符串计算编辑距离,然后进行排序,将编辑距离小的放在上面显示。具体 Demo 做在 jsfiddle 上面了:

width="100%" height="300" src="http://jsfiddle.net/yujiangshui/ds6ztf8d/embedded/" allowfullscreen="allowfullscreen" frameborder="0" style="color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Nimbus Sans L', Arial, 'Liberation Sans', 'Hiragino Sans GB', 'Source Han Sans CN', 'Source Han Sans SC', 'Microsoft YaHei', 'Wenquanyi Micro Hei', 'WenQuanYi Zen Hei', 'ST Heiti', SimHei, 'WenQuanYi Zen Hei Sharp', sans-serif; font-size: 14.3999996185303px; line-height: 24.4799995422363px;">

也可以点击这里查看。

使用起来是有点效果的,比如:

但是也有很大的偏差,比如要搜索的关键词和相似结果编辑距离太大,超过了同等长度的不同字符,这时候就会出现错误的推荐:

如果数据足够多,各种情况都具备,那么推荐准确的可能性更大些。如果要改善这个功能,可能需要结合中文分词对关键词进行匹配综合等等,超出本文范畴这里不再赘述。

如果你有更好的方法和思路,欢迎留言讨论。


这篇关于使用 JavaScript 实现简单候选项推荐功能(模糊搜索)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/288215

相关文章

Spring Security基于数据库的ABAC属性权限模型实战开发教程

《SpringSecurity基于数据库的ABAC属性权限模型实战开发教程》:本文主要介绍SpringSecurity基于数据库的ABAC属性权限模型实战开发教程,本文给大家介绍的非常详细,对大... 目录1. 前言2. 权限决策依据RBACABAC综合对比3. 数据库表结构说明4. 实战开始5. MyBA

AJAX请求上传下载进度监控实现方式

《AJAX请求上传下载进度监控实现方式》在日常Web开发中,AJAX(AsynchronousJavaScriptandXML)被广泛用于异步请求数据,而无需刷新整个页面,:本文主要介绍AJAX请... 目录1. 前言2. 基于XMLHttpRequest的进度监控2.1 基础版文件上传监控2.2 增强版多

使用Python自建轻量级的HTTP调试工具

《使用Python自建轻量级的HTTP调试工具》这篇文章主要为大家详细介绍了如何使用Python自建一个轻量级的HTTP调试工具,文中的示例代码讲解详细,感兴趣的小伙伴可以参考一下... 目录一、为什么需要自建工具二、核心功能设计三、技术选型四、分步实现五、进阶优化技巧六、使用示例七、性能对比八、扩展方向建

Spring Security方法级安全控制@PreAuthorize注解的灵活运用小结

《SpringSecurity方法级安全控制@PreAuthorize注解的灵活运用小结》本文将带着大家讲解@PreAuthorize注解的核心原理、SpEL表达式机制,并通过的示例代码演示如... 目录1. 前言2. @PreAuthorize 注解简介3. @PreAuthorize 核心原理解析拦截与

一文详解JavaScript中的fetch方法

《一文详解JavaScript中的fetch方法》fetch函数是一个用于在JavaScript中执行HTTP请求的现代API,它提供了一种更简洁、更强大的方式来处理网络请求,:本文主要介绍Jav... 目录前言什么是 fetch 方法基本语法简单的 GET 请求示例代码解释发送 POST 请求示例代码解释

Java图片压缩三种高效压缩方案详细解析

《Java图片压缩三种高效压缩方案详细解析》图片压缩通常涉及减少图片的尺寸缩放、调整图片的质量(针对JPEG、PNG等)、使用特定的算法来减少图片的数据量等,:本文主要介绍Java图片压缩三种高效... 目录一、基于OpenCV的智能尺寸压缩技术亮点:适用场景:二、JPEG质量参数压缩关键技术:压缩效果对比

Java调用C++动态库超详细步骤讲解(附源码)

《Java调用C++动态库超详细步骤讲解(附源码)》C语言因其高效和接近硬件的特性,时常会被用在性能要求较高或者需要直接操作硬件的场合,:本文主要介绍Java调用C++动态库的相关资料,文中通过代... 目录一、直接调用C++库第一步:动态库生成(vs2017+qt5.12.10)第二步:Java调用C++

Redis分片集群的实现

《Redis分片集群的实现》Redis分片集群是一种将Redis数据库分散到多个节点上的方式,以提供更高的性能和可伸缩性,本文主要介绍了Redis分片集群的实现,具有一定的参考价值,感兴趣的可以了解一... 目录1. Redis Cluster的核心概念哈希槽(Hash Slots)主从复制与故障转移2.

springboot+dubbo实现时间轮算法

《springboot+dubbo实现时间轮算法》时间轮是一种高效利用线程资源进行批量化调度的算法,本文主要介绍了springboot+dubbo实现时间轮算法,文中通过示例代码介绍的非常详细,对大家... 目录前言一、参数说明二、具体实现1、HashedwheelTimer2、createWheel3、n

使用Python实现一键隐藏屏幕并锁定输入

《使用Python实现一键隐藏屏幕并锁定输入》本文主要介绍了使用Python编写一个一键隐藏屏幕并锁定输入的黑科技程序,能够在指定热键触发后立即遮挡屏幕,并禁止一切键盘鼠标输入,这样就再也不用担心自己... 目录1. 概述2. 功能亮点3.代码实现4.使用方法5. 展示效果6. 代码优化与拓展7. 总结1.