计算字符串相似度的一些方法

python 专栏收录该内容
29 篇文章 2 订阅

产品出了一个奇怪的需求,想通过字符串相似度取匹配城市= =(当然,最后证实通过字符串相似度取判断两个字符串是不是一个城市是不对的!!!)

这里就记录一下我计算字符串(英文字符串)相似度的方法吧~

参考文档:

Levenshtein

  • Levenshtein.hamming(str1, str2)

    计算汉明距离。要求str1和str2必须长度一致。是描述两个等长字串之间对应位置上不同字符的个数。

    用法:

    >>> import Levenshtein     
    >>> Levenshtein.hamming('abc', 'cba')
    2
    >>> Levenshtein.hamming('abc', 'def')
    3
    
  • Levenshtein.distance(str1, str2)

    计算编辑距离(也成Levenshtein距离)。是描述由一个字串转化成另一个字串最少的操作次数,在其中的操作包括插入、删除、替换。

    用法:

    >>> Levenshtein.distance('abc', 'ab')
    1
    >>> Levenshtein.distance('cxy', 'ab')
    3
    
  • Levenshtein.ratio(str1, str2)

    计算莱文斯坦比。计算公式 r = (sum - ldist) / sum, 其中sum是指str1 和 str2 字串的长度总和,ldist是类编辑距离

    注意:这里的类编辑距离不是Levenshtein.distance(str1, str2)所说的编辑距离,Levenshtein.distance(str1, str2)中三种操作中每个操作+1,而在此处,删除、插入依然+1,但是替换+2
    这样设计的目的:ratio(‘a’, ‘c’),sum=2,按2中计算为(2-1)/2 = 0.5,’a’,'c’没有重合,显然不合算,但是替换操作+2,就可以解决这个问题。

    用法:

    >>> Levenshtein.ratio('a,cdsf', 'abcd')		      
    0.6
    

difflib

我主要用的是SequenceMatcher, 因此,本次只介绍SequenceMatcher.

SequenceMatcher是可以对两个可序列化的对象进行比较的类

官网上的用法是:

>>> s = SequenceMatcher(lambda x: x == " ",
   ...                     "private Thread currentThread;",
   ...                     "private volatile Thread currentThread;")
   >>> print(round(s.ratio(), 3))
   0.866

第一个参数为一个函数,主要用来去掉自己不想算在内的元素;如果没有,可以写None
后面两个参数就是需要比较的两个对象了

余弦定理

相似度算法之余弦相似度

通过阅读上面的文章,我们可以简单总结计算相似度的几个步骤:

  1. 列出所有出现的字母,并分别统计两个字符串出现这些字母的次数。这里我是这样写的,利用from collections import Counter, OrderedDict

    方法:

    >>> from collections import Counter, OrderedDict
    >>> from copy import deepcopy
    >>> a = 'abc'
    >>> b = 'bcde'
    >>> item = set(a) | set(b)
    >>> item
    {'b', 'c', 'e', 'd', 'a'}
    >>> model = OrderedDict().fromkeys(item)
    >>> model
    OrderedDict([('b', None), ('c', None), ('e', None), ('d', None), ('a', None)])
    >>> model1 = deepcopy(model)
    >>> model2 = deepcopy(model)
    >>> model1.update(Counter(a))
    >>> model1
    OrderedDict([('b', 1), ('c', 1), ('e', None), ('d', None), ('a', 1)])
    >>> model2.update(Counter(b))
    >>> model2
    OrderedDict([('b', 1), ('c', 1), ('e', 1), ('d', 1), ('a', None)])
    

    这样写的原因是,在比较词频的时候,要保证每个字母的顺序是一样的~

  2. 利用余弦公式计算相似度

    方法:

    >>> import math
    >>> sum = 0	#分子
    >>> q1 = 0	#分母
    >>> q2 = 0	#分母
    >>> for i in item:
    	a = model1[i] if type(model1[i]) != type(None) else 0
    	b = model2[i] if type(model2[i]) != type(None) else 0
    	sum += a * b
    	q1 += pow(a, 2)
    	q2 += pow(b, 2)
    >>> sum
    2
    >>> q1
    3
    >>> q2
    4
    >>> result = float(sum) / (math.sqrt(q1) * math.sqrt(q2))
    >>> result
    0.5773502691896258
    

这样就算出相似度啦~

ps:本文说的计算的字符串,全是英文字符串~~

  • 1
    点赞
  • 2
    评论
  • 4
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

评论 2 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:猿与汪的秘密 设计师:我叫白小胖 返回首页

打赏作者

一只路过的小码农cxy

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值