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

当我们使用 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];

}

实际应用

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

原文地址:http://www.yujiangshui.com/javascript-levenshtein-distance/

时间: 2024-10-04 21:35:44

使用 JavaScript 实现简单候选项推荐功能(模糊搜索)【收藏】【转】的相关文章

JavaScript基础--简单功能的计算器(十一)

1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 2 <html xmlns="http://www.w3.org/1999/xhtml"> 3 <head> 4 <meta http-equiv="

自己实现简单的AOP(三) 实现增强四项基本功能

前面的两篇随笔,都是只是个铺垫,真正实现增强四项基本功能的重头戏,在本篇随笔中, 本文将通过AOP实现如下的四个基本功能: /// <para>1.自动管理数据库连接[可选]</para>/// <para>2.自动管理数据库事务,当接收到异常后(无论什么异常)事务将自动回滚[可选]</para>/// <para>3.服务级加锁[必选]</para>/// <para>4.以统一方式处理 服务异常 及 错误, 包括数据库

javascript自定义简单map对象功能

这里介绍一种js创建简单map对象的方法: function Map() { //创建object对象, 并给object对象添加key和value属性 var obj1=new Object(); var obj2=new Object(); obj1.key="zhangsan" ; obj1.value=23; obj2.key="lisi"; obj2.value=25; //创建一个数组,将创建的object对象放如到数组中去 var map=new Ar

你相信么,只需一个函数5行JS代码即可在Javascript中实现完整的AOP功能

你相信么,只需一个函数5行JS代码即可在Javascript中实现完整的AOP功能, 你相信么,在JavaScript只需一个函数5行代码即可实现完整的面向方面AOP编程功能.这5行代码的功能包括: 无限层次的函数无害拦截 函数执行前拦截 检查函数的参数值 重新设定函数的参数值 函数执行后拦截 检查函数执行后的返回结果 重新设定函数的返回结果 虽然动态函数式语言的效率是一个存在的问题,但是对于它的高度灵活性,简直让人令人惊叹不已,剧赞. 这个小小的函数源自于和爱明兄的一次讨论:在javascri

jquery 实现的一款超简单的图片切换功能

<html><head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script type="text/javascript" src="./assets/js/jquery.js"></script></head><style> </st

vs2015使用Apache Cordova用JavaScript来访问本地设备的功能,比如摄像头、加速计

看到下面这张图就代表着我VS2015 跨平台Moblie开发工具安装成功了. 上周安装成功后本想一睹跨平台开发的乐趣,可是一直找不到合适的入口.这周又来捯饬一下结果发现了一个入口.于是来写一个Hello World和大家分享一下.我们先来了解一下主角吧,那就是Apache Cordova. Apache Cordova是一套设备API,允许移动应用的开发者使用JavaScript来访问本地设备的功能,比如摄像头.加速计.它可以与UI框架(如jQuery Mobile或Dojo Mobile或Se

Python django实现简单的邮件系统发送邮件功能

Python django实现简单的邮件系统发送邮件功能 本文实例讲述了Python django实现简单的邮件系统发送邮件功能. django邮件系统 Django发送邮件官方中文文档 总结如下: 1.首先这份文档看三两遍是不行的,很多东西再看一遍就通顺了.2.send_mail().send_mass_mail()都是对EmailMessage类使用方式的一个轻度封装,所以要关注底层的EmailMessage.3.异常处理防止邮件头注入.4.一定要弄懂Email backends 邮件发送后

Linux主机实现简单的路由转发功能

只要在Linux主机上添加一些简单的路由条目, 这些Linux主机就可以充当简单路由器的功能. 在实际生产坏境中, 当我们需要一台路由器简单作为转发数据, 但是手上却没有路由器的话, 我们就可以指定一台Linux主机充当一个简单的路由器,实现路由简单的转发. 上面所诉尤其强调简单, 所以说只是实现简单的路由的功能, 如果要实现非常复杂的功能的话, 一台Linux主机可能无法实现你想要的条件. 实验坏境: 基于VMware上的4台虚拟主机,主机名为R1.R2的两台主机(都是centos6.8系统)

Javascript实现简单的选项卡

在线演示:http://jsfiddle.net/Web_Code/TbPDd/embedded/result/ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml&