2019独角兽企业重金招聘Python工程师标准>>>

我们爬来了一些数据,接下来以豆瓣畅销书为例。

爬虫爬来的数据有

['艾伦•图灵传','深入理解计算机系统(原书第2版)','C++ Primer 中文版(第 5 版)','深入理解计算机系统','Web性能权威指南']

而我们系统中原有的数据有

['艾伦·图灵传','深入理解计算机系统(原书第2版)','C++ Primer 中文版(第 4 版)','深入理解计算机系统']

做前端的同志可能一眼就看出来了,两个数组中有三个元素是因为全半角的缘故,是不能全词匹配的,而前两本书事实上是同一本书。而《深入理解计算机系统》是可以全词匹配到的,《Web性能权威指南》一书是可以直接添加到数据库的。


解决方案一:

这个任务大可以交给编辑去做,但是时间复杂度为 N^2,连程序都吃不消跑,更别提让编辑做了。

解决方案二:

去除所有的标点符号,或者将所有全角符号转化为半角。 去掉所有空格。 然后进行全词匹配,这样做有些鲁莽,但是速度一点也不慢。

解决方案三:

我想到了用 jieba 进行中文分词,

import jieba
book = '艾伦·图灵传'
word = jieba.cut(book)
words = list(word)
# words = ['艾伦', '·', '图灵', '传']

对于每本书我们都可以进行这样一个分词操作,并可以考虑将标点符号去除。 然后看每两个数组的元素的重合情况,但要考虑归一化,原因如下:

  1. ‘Python 开发指南’ 和 ‘皇家 Python 开发指南’ 元素的重合数为 3 个单词。
  2. ‘Python 开发指南’ 和 ‘皇家 Python 超级无敌开发指南’ 元素的重合数为 3 个单词。

显然第 1 组看起来会比第 2 组相似一些,但是重合数是一样的。使用重合数显然不科学,我们可以通过除以分词后单词总数来计算它们的重合率。

解决方案四:

在想解决方案三的时候,我回忆起了以前做聚类算法的时候用的各种距离算法,对于实数的欧几里得距离,用在 k-modes 中的对于类型数据的相异度量算法,前者在这里显然不适用,后者又显得有点小题大做。然后我发现了一种叫做编辑距离 Edit Distance 的算法,又称 Levenshtein 距离。[1]

编辑距离是指两个字串之间,由一个转成另一个所需的最少编辑操作次数。 维基上给出了一个例子: 'kitten' 和 'sitting' 的编辑距离为3:

  1. kitten → sitten (s 替换成 k)
  2. sitten → sittin (i 替换成 e)
  3. sittin → sitting (加上一个 g)

碰巧的是有一个开源的 python 包刚好可以计算 Levenshtein 距离,可以通过以下安装:

pip install python-Levenshtein

然后就可以计算编辑距离了:

import Levenshtein
texta = '艾伦·图灵传'
textb = '艾伦•图灵传'
print Levenshtein.distance(texta,textb)
# 3

很自然地会有这个疑问,为什么这里的编辑距离会是3,我们来看看具体进行的编辑操作。

Levenshtein.editops('艾伦·图灵传', '艾伦•图灵传')
[('insert', 6, 6), ('replace', 6, 7), ('replace', 7, 8)]

看起来只有一个字符的区别,但是这里做了三次编辑操作,为什么?我们来打印一下这两个字符串的具体表达:

In [4]: a='艾伦·图灵传'
In [5]: a
Out[5]: '\xe8\x89\xbe\xe4\xbc\xa6\xc2\xb7\xe5\x9b\xbe\xe7\x81\xb5\xe4\xbc\xa0'
In [6]: a='艾'
In [7]: a
Out[7]: '\xe8\x89\xbe'

看到这里就明白了,我们犯了一个错误,把这两个字符串存成了 string 类型,而在 string 类型中,默认的 utf-8 编码下,一个中文字符是用三个字节来表示的。于是这里又牵扯到了 Python 中的 string 和 unicode 的区别。然而在这个字节串中,我们的编辑距离,的的确确是3。

现在重新来计算距离。

print Levenshtein.distance(u'艾伦·图灵传',u'艾伦•图灵传')
# 1

现在就正确了,现在的编辑距离1就代表了两本书的名字的差别度量。这时候就要开始做归一化了,而巧的是,我们发现这个 Levenshtein 包中自带了一个相似度函数 jaro(),它可以接受两个字符串并给出从0到1范围内的相似度。下面所显示的0.888888888889便表示了这两个字符串的相似度。

print Levenshtein.jaro(u'艾伦·图灵传',u'艾伦•图灵传')
# 0.888888888889

然后我们可以写个嵌套的 for 循环,设置一个阈值 threshold,计算每一对书本的相似度,当他们超过某一阈值时,进行处理。这里要注意的就是,不要重复检验书本对,即检测(书本 A,书本 B)和(书本 B,书本 A),这样可以避免 N^2 的时间复杂度。


当然最后其实还是需要人工介入的,比如遇到第三本书这种情况,版次不一样并不算同一本书。再当然,我们是可以对所有版次有关的字符进行特殊处理,比如出现版次字符,而且两本书不相同的时候,把距离函数的输出值加上一个修正参数。不过,这种情况太多太多,还是用人工处理好了,此时的两本书为同一本书的机率是很高的。再不然,只能上机器学习了,但是也是要你有训练样本的。

参考文献: [1] wikipedia Levenshtein_distance [2] Levenshtein Document

转载于:https://my.oschina.net/shinedev/blog/494098

使用 Levenshtein 寻找彼此相似的字符串对相关推荐

  1. 通过正则寻找符合要求的字符串

    一.findall是pd.Series.str所特有的(regex也有这个函数,字符串类没有这个函数): 二.字符串无论单独打印还是以series序列的形式打印,都没有定义时最外面的那个引号无论单双: ...

  2. 【C语言】(错题整理) 寻找完数、字符串中各类字符数的统计、最大公约数和最小公倍数、回文数计算 (循环、函数相关内容)

    目录 一.循环 1.寻找完数(计算因子例题) 2.字符串中各类字符数的统计 3.最大公约数和最小公倍数 求最大公约数: 最小公倍数:最小公倍数=两整数的乘积÷最大公约数 二.函数 1.回文数计算 本篇 ...

  3. 计算字符串相似度算法—Levenshtein

    什么是Levenshtein Levenshtein 距离,又称编辑距离,指的是两个字符串之间,由一个转换成另一个所需的最少编辑操作次数.许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删 ...

  4. 寻找蛇形字符串python实现

    输入一个字符串(不含空格),请寻找输入中包含的所有蛇形字符串. 1. 蛇形字符串的定义: 1.1 字符对定义:字符对有同一字母的大小组成(前大后小),如:Aa,Dd. 1.2 蛇形字符串中包含的字符对 ...

  5. c++ 模糊搜索 正则表达式_模糊搜索算法(近似字符串匹配算法)

    考虑到您正在尝试对学校名称列表进行模糊搜索,因此我认为您不希望使用Levenshtein距离之类的传统字符串相似性. 我的假设是,您正在接受用户的输入(键盘输入或通过电话说出),并且想要快速找到匹配的 ...

  6. 2046幻想_寻找一个幻想足球的名字

    2046幻想 Looking for a new fantasy football team name? I extracted over 500,000 fantasy football team ...

  7. Levenshtein distance 编辑距离算法

    这几天再看 virtrual-dom,关于两个列表的对比,讲到了 Levenshtein distance 距离,周末抽空做一下总结. Levenshtein Distance 介绍 在信息理论和计算 ...

  8. 有条件截取字符串_Python小课堂之木辛老师特别讲解:再次深入浅出字符串的格式化...

    我们已经学习了字符串和数字基础的处理方法和逻辑,大家有没有觉得使用起来很方便,编程的过程中也是很给力的呀!其实Python还有更多字符串处理的方法,大家今天就一起来体验一下吧 小朋友们可以先复习一下前 ...

  9. 【C 语言】指针 与 数组 ( 指针 | 数组 | 指针运算 | 数组访问方式 | 字符串 | 指针数组 | 数组指针 | 多维数组 | 多维指针 | 数组参数 | 函数指针 | 复杂指针解读)

    相关文章链接 : 1.[嵌入式开发]C语言 指针数组 多维数组 2.[嵌入式开发]C语言 命令行参数 函数指针 gdb调试 3.[嵌入式开发]C语言 结构体相关 的 函数 指针 数组 4.[嵌入式开发 ...

最新文章

  1. Windows Server 2012 从入门到精通系列之如何提高DC持续性?
  2. 现代中产男人必备的8种气质[zt] 来自9G群里发的,据说是BF推荐给9G的
  3. UNPIVOT的详细说明
  4. CSocketFile类
  5. python中的深浅拷贝
  6. 【BZOJ4562】食物链,拓扑DP
  7. 远程连接Ubuntu服务器
  8. 原生ajax接收json字符串(简单介绍)
  9. 并发数 = QPS*平均响应时间(转)
  10. MPU6050六轴传感器的原理及编程说明
  11. visio怎么画球_快速学习Visio 门球制图
  12. ,PLCSIM、SIMIT、Amesim、NX MCD、 Process Simulate、Plant Simulation,一文带你了解西门子整个虚拟调试与仿真软硬件体系
  13. 虚拟机使用本地服务器配置,虚拟机搭建本地云服务器配置
  14. 运行在网络处理器上的嵌入式Linux系统
  15. 买股不如买基?Python实现快速追踪基金的收益情况!谁还不是个买基高手?
  16. ftp 服务器 性能,Xlight FTP服务器网络性能测试
  17. 银行卡号- 查询银行卡信息
  18. 【计算机网络】计算机网络-分组发送相关计算
  19. 小程序团购商品CPS接入,实现达人分佣模式
  20. opencv人脸识别之让电脑分清吴彦祖和彭于晏 (LBPH)

热门文章

  1. Mac air装 win10 ,总是提示拷贝windows安装文件失败!?
  2. FairyGUI按钮动效的混用
  3. 从零开始开发SSM项目-博客系统实战
  4. 新建vue-cli项目body与页面边框存在间隙
  5. 重磅!L4级自动驾驶硬件方案来啦!
  6. PC按键精灵读取txt文本出现乱码怎么办?按键精灵手机助手读取txt文本中文变问号怎么办?
  7. 深度技术GHOST WIN7 SP1 2013 新春版
  8. WIndows内核学习笔记:分页机制——PAE分页模式
  9. 2021年秋招面经分享·平头哥【芯片设计/验证/DFT工程师】
  10. ue4创建一个游戏模式Game mode