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

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

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

    前面的两篇随笔,都是只是个铺垫,真正实现增强四项基本功能的重头戏,在本篇随笔中, 本文将通过AOP实现如下的四个基本功能: /// <para>1.自动管理数据库连接[可选]</pa ...

  2. 开源巨献:年度最佳 JavaScript 和 CSS 开源库推荐!

    作者:编辑部的故事   <  开源巨献:年度最佳 JavaScript 和 CSS 开源库推荐!   > 开源巨献:年度最佳 JavaScript 和 CSS 开源库推荐! Tutoria ...

  3. Win10系列:JavaScript 项目模板和项模板

    使用Visual Studio 开发Windows应用商店应用时,通过其提供的模板可以帮助我们快速地创建一个应用.其中,在新建一个Windows应用商店应用程序项目时可以在项目模板中选择所需要的模板类 ...

  4. JavaScript做简单的购物车效果(增、删、改、查、克隆)

    比如有时候遇到下面这种情况,点击加入购物车,然后在上方的购物车中动态的添加商品以及商品的信息,我们就可以通过JavaScript实现简单的这些操作. 首先我们需要在html文档中,通过css对页面的布 ...

  5. Selenium + PhantomJS + python 简单实现爬虫的功能

    Selenium 一.简介 selenium是一个用于Web应用自动化程序测试的工具,测试直接运行在浏览器中,就像真正的用户在操作一样 selenium2支持通过驱动真实浏览器(FirfoxDrive ...

  6. 实际例子描述和分析“猎豹抢票跨站推荐功能有票刷不到”的疑似bug

    前言 快过年了,又到了一年抢票时.今年douba和douma计划要带着doudou回姥姥家.昨天在家用抢票软件居然发现了一个bug,那就是在猎豹抢票中跨站推荐的车票几天里一直是没有,但是在12306手 ...

  7. Javascript的简单测试环境

    在<JavaScript忍者秘籍>2.4测试条件基础知识中,作者给出了一个精简版的assert和assert组的实现,对于初学者而言,这无疑是一个很好的例子,既让我们得到了一个好用的小工具 ...

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

    Python django实现简单的邮件系统发送邮件功能 本文实例讲述了Python django实现简单的邮件系统发送邮件功能. django邮件系统 Django发送邮件官方中文文档 总结如下: ...

  9. Javascript学习-简单测试环境

    Javascript学习-简单测试环境 在<JavaScript忍者秘籍>2.4测试条件基础知识中,作者给出了一个精简版的assert和assert组的实现,对于初学者而言,这无疑是一个很 ...

随机推荐

  1. JavaScript函数的概念

    函数是这样的一段代码,它只定义一次,但可能被执行或调用任意多次. JavaScript函数是参数化的:函数的定义会包含形参,这些参数在函数的整体中像局部变量一样工作.函数调用时会为形参提供实参的值.除 ...

  2. 手动处理datanode磁盘间使用不均的问题

    http://wiki.apache.org/hadoop/FAQ#On_an_individual_data_node.2C_how_do_you_balance_the_blocks_on_the ...

  3. oracle 倒库后insert id冲突的问题

    错误为:ORA-00001: unique constraint violated 把test库的数据导入到另一个库后,忘记修改自增id sequence的nextval了,因此,当前的数据库中数据和 ...

  4. Caffe 单独测试添加的layer

    转载请注明出处,楼燚(yì)航的blog,http://home.cnblogs.com/louyihang-loves-baiyan/ 一般我们在使用Caffe的时候,可能需要根据自己的任务需求添加 ...

  5. hibernate inverse属性的作用

    hibernate配置文件中有这么一个属性inverse,它是用来指定关联的控制方的.inverse属性默认是false,若为false,则关联由自己控制,若为true,则关联由对方控制.见例子: 一 ...

  6. 洛谷P1462 通往奥格瑞玛的道路[二分答案 spfa 离散化]

    题目背景 在艾泽拉斯大陆上有一位名叫歪嘴哦的神奇术士,他是部落的中坚力量 有一天他醒来后发现自己居然到了联盟的主城暴风城 在被众多联盟的士兵攻击后,他决定逃回自己的家乡奥格瑞玛 题目描述 在艾泽拉斯, ...

  7. Python-11-RabbitMQ、Redis使用

    RabbitMQ RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统.他遵循Mozilla Public License开源协议. MQ全称为Message Queue, 消息队列(M ...

  8. bash shell

    Linux的shell 与windows只有一种批处理脚本不同,由于早年的Unix年代,发展者众,出现了各种不同的distribution,因此也随着不同的distribution出现了各自的shel ...

  9. vector容器删除某些元素且释放内存

    1,size和capacity size: 指目前容器中实际有多少元素,对应的resize(size_type)会在容器尾添加或删除一些元素,来调整容器中实际的内容,使容器达到指定的大小. capac ...

  10. 第二次团队作业——预则立&&他山之石

    Deadline: 2016.10.16 22:00pm 一.确立团队选题,建立和初步熟悉团队git的协作方式.项目后续的代码.文档都要通过github增量式管理.实现文档的版本化和增量式管理. 二. ...