国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

python字符串模糊匹配,并計(jì)算匹配分?jǐn)?shù)

這篇具有很好參考價(jià)值的文章主要介紹了python字符串模糊匹配,并計(jì)算匹配分?jǐn)?shù)。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

一、thefuzz

thefuzz包以前叫fuzzywuzzy,0.19版本開始改名為thefuzz,github地址:

GitHub - seatgeek/thefuzz: Fuzzy String Matching in Python

可以通過命令pip install thefuzz安裝此包。用法還是比較簡單的:

from thefuzz import fuzz

fuzz.ratio("test", "test!")

>>89

上面兩個(gè)字符串的相似度為89%。

二、相似度ratio的計(jì)算

我們先看看這個(gè)包下面的源碼,來查看thefuzz是怎么實(shí)現(xiàn)模糊匹配的。thefuzz源碼包的結(jié)構(gòu)如下:

python字符串模糊匹配,并計(jì)算匹配分?jǐn)?shù)

先看看ratio方法源碼:

def ratio(s1, s2):
    s1, s2 = utils.make_type_consistent(s1, s2)

    m = SequenceMatcher(None, s1, s2)
    return utils.intr(100 * m.ratio())

?可以看到,ratio方法用到了一個(gè)比較關(guān)鍵的類SequenceMatcher,但是這個(gè)類卻有可能來自兩個(gè)不同的地方。

2.1?SequenceMatcher的來源

看看fuzzy.py的頭部代碼:

import platform
import warnings

try:
    #從當(dāng)前文件夾的StringMatcher中導(dǎo)入StringMatcher
    from .StringMatcher import StringMatcher as SequenceMatcher
except ImportError:
    if platform.python_implementation() != "PyPy":
        warnings.warn('Using slow pure-python SequenceMatcher. Install python-Levenshtein to remove this warning')
    from difflib import SequenceMatcher

#導(dǎo)入當(dāng)前文件夾的utils包,.代表當(dāng)前目錄
from . import utils

上面代碼涉及了一個(gè)導(dǎo)入問題,即先從當(dāng)前文件StringMatcher中導(dǎo)入StringMatcher,如果導(dǎo)入出現(xiàn)異常,就去difflib中導(dǎo)入SequenceMatcher。

正如上面第一張圖中看到的,當(dāng)然文件夾下面確實(shí)有一個(gè)叫StringMatcher.py的文件,也看看它前面的代碼:

from Levenshtein import *
from warnings import warn

class StringMatcher:
.............
.............

可以看出,這個(gè)StringMatcher類引用了Levenshtein包,這個(gè)包也是用來計(jì)算字符串模糊匹配的,效率上來說,有可能比difflib中的SequenceMatcher快4-10倍。

Levenshtein包是用C語言寫的,比較復(fù)雜,最初的項(xiàng)目地址:

GitHub - miohtama/python-Levenshtein: The Levenshtein Python C extension module contains functions for fast computation of Levenshtein distance and string similarity

后來這個(gè)作者沒有維護(hù)了,然后由另一個(gè)在維護(hù),項(xiàng)目的地址在這里:

GitHub - ztane/python-Levenshtein: The Levenshtein Python C extension module contains functions for fast computation of Levenshtein distance and string similarity

但是,這個(gè)頁面上,作者也說了,他也7年不維護(hù)了,現(xiàn)在沒找到新的維護(hù)者。

不管怎么說,如果要使用Levenshtein,還是可以安裝的:

pip install python-Levenshtein

總結(jié)就是,thefuzz有兩種實(shí)現(xiàn)方式,一種是依賴difflib,另一種依靠?python-Levenshtein。先看簡單的difflib。

2.2 difflib包中的SequenceMatcher

首先導(dǎo)入:

from difflib import SequenceMatcher

這個(gè)類的主要作用是計(jì)算兩個(gè)匹配字符串的相似度,如下:

s = SequenceMatcher(None, "abcde", "bcde")
s.ratio()

輸出值為0.888888。這個(gè)是怎么計(jì)算的呢?可以查看difflib.py的源代碼(我的電腦在D:\ProgramData\Miniconda3\Lib目錄下),如下:

def ratio(self):
    matches = sum(triple[-1] for triple in self.get_matching_blocks())
    return _calculate_ratio(matches, len(self.a) + len(self.b))

這個(gè)方法涉及到兩個(gè)比較重要的方法,一個(gè)是get_matching_blocks(),這個(gè)方法用于獲取匹配的字符塊。另一個(gè)方法_calculate_ratio,用于計(jì)算相似度,先看_calculate_ratio,代碼如下:

def _calculate_ratio(matches, length):
    if length:
        return 2.0 * matches / length
    return 1.0

上面代碼的第三行是關(guān)鍵,matches表示的字符個(gè)數(shù),length是兩個(gè)字符串加起來的總長度。如上面的"abcde"和 "bcde",ratio的計(jì)算方法就是2*4/9,即8/9=0.888888。

再看看get_matching_blocks方法。這個(gè)方法比較復(fù)雜,我們先來看下,這個(gè)方法的用法:

s = SequenceMatcher(None, "abchde", "bcde")
print(s.get_matching_blocks())

輸出如下:

[Match(a=1, b=0, size=2), Match(a=4, b=2, size=2), Match(a=6, b=4, size=0)]?

什么意思?從方法的名字大概就能看出來,就是獲得匹配的所有字符塊。上面的代碼輸出了3個(gè)Match對象,Match(a=1, b=0, size=2)的意思是"abchde"從索引1(a=1)開始,"bcde"從索引0(b=0)開始,匹配到2(size=2)個(gè)相等字符,即“bc”。

最后一個(gè)Match(a=6, b=4, size=0)是固定的,a、b代表兩個(gè)字符串的長度,size=0固定不變。用代碼描述如下:

(len(a), len(b), 0)

但是如果前面字串符已經(jīng)匹配過,就不會(huì)再進(jìn)行匹配了,如下:

s = SequenceMatcher(None, "bc", "abchdebc")
print(s.get_matching_blocks())?

輸出:

?[Match(a=0, b=1, size=2), Match(a=2, b=8, size=0)]

即“bc”只匹配了第一次的位置,后面就算出現(xiàn)和它一樣的字符串,也不再進(jìn)行匹配。?

三、process模塊

從第一張圖中可以看到,除了fuzz.py這個(gè)文件,還有一個(gè)叫process.py的文件,process模塊常用的是從候選列表中,返回與目標(biāo)字符串最相似的一個(gè)結(jié)果。來看一個(gè)簡單的例子:

from thefuzz import fuzz,process

choices = ["hello world", "hello china", "hello beijing"]
print(process.extractOne("china",choices))

#輸出內(nèi)容
>>('hello china', 90)

正如上面代碼所示,process最常用的用法是從眾多字符串中,找到最佳匹配的字符串。

process.extractOne的格式如下:

extractOne(query, choices, processor=default_processor, scorer=default_scorer, score_cutoff=0):

"""
Args:
    query: A string to match against
    choices: A list or dictionary of choices, suitable for use with extract().
    processor: Optional function for transforming choices before matching.
    scorer: Scoring function for extract().
    score_cutoff: Optional argument for score threshold. If the best
            match is found, but it is not greater than this number, then
            return None anyway ("not a good enough match").  Defaults to 0.

Returns:
    A tuple containing a single match and its score, if a match
    was found that was above score_cutoff. Otherwise, returns None.
"""

query:查詢的字符串;

choices:?待匹配的字符串列表或者字典;

processor:可選參數(shù),轉(zhuǎn)換器,在匹配前先對choices進(jìn)行轉(zhuǎn)換處理;

scorer:可選參數(shù),分?jǐn)?shù)器,用于計(jì)算分?jǐn)?shù);

score_cutoff:可選參數(shù),這個(gè)參數(shù)的作用是設(shè)置一個(gè)分?jǐn)?shù)門檻(默認(rèn)為0),如果小于這個(gè)分?jǐn)?shù),就不返回匹配的字符串,而是返回一個(gè)None。

extractOne返回的結(jié)果是一個(gè)tuple元組(最佳匹配結(jié)果,分?jǐn)?shù))。

我們比較關(guān)心的一個(gè)問題是,這個(gè)分?jǐn)?shù)是怎么計(jì)算的?看看下面例子:

from thefuzz import fuzz,process

print(fuzz.ratio("china","hello china"))

choices = ["hello world", "hello china", "hello beijing"]
print(process.extractOne("china",choices))

#輸出內(nèi)容
>>62
>>('hello china', 90)

可以看出,fuzz.ratio與process.extractOne分?jǐn)?shù)的計(jì)算方式不一樣(一個(gè)是62分,一個(gè)90分)。fuzz.ratio的計(jì)分方式,上面已經(jīng)講了,下面來看看extractOne的計(jì)分方式。

extractOne的源碼如下:

def extractOne(query, choices, processor=default_processor, scorer=default_scorer, score_cutoff=0):
    best_list = extractWithoutOrder(query, choices, processor, scorer, score_cutoff)
    try:
        return max(best_list, key=lambda i: i[1])
    except ValueError:
        return None

我們剛才說了,第三個(gè)參數(shù)scorer是用于計(jì)分的,它的默認(rèn)值為default_scorer,那我們先找到這個(gè)default_scorer的值:

default_scorer = fuzz.WRatio

即默認(rèn)的計(jì)分方式為fuzz.WRatio,那么我們回到fuzz.py中,看看WRatio是做什么的?

from thefuzz import fuzz

default_scorer = fuzz.WRatio
default_scorer("china", "hello china")

#輸出
>> 90

?可以看出,WRatio的計(jì)分方式確實(shí)和上面的extractOne相同,都是90分。WRatio的計(jì)分方式比較復(fù)雜,涉及到一個(gè)權(quán)重(weight)的概念,它是基于fuzz.ratio()的基礎(chǔ)上,做了進(jìn)一步的校正。

如果我們不想采用WRatio的計(jì)分方式,或者想采用fuzz.ratio()的計(jì)分方式來提取最佳匹配結(jié)果,可以這樣:

from thefuzz import fuzz,process

print(fuzz.ratio("china","hello china"))

choices = ["hello world", "hello china", "hello beijing"]
print(process.extractOne("china",choices,scorer=fuzz.QRatio))

#輸出
>>62
>>('hello china', 62)

上面代碼的計(jì)分結(jié)果都是62分,因?yàn)閒uzz.QRatio的內(nèi)部,除了對參數(shù)進(jìn)行了一些簡單的處理以外,直接調(diào)用fuzz.ratio()方法返回了結(jié)果。所以fuzz.QRatio和fuzz.ratio()的計(jì)分方式完全相同。

fuzz.QRatio源代碼:

# q is for quick
def QRatio(s1, s2, force_ascii=True, full_process=True):

    if full_process:
        p1 = utils.full_process(s1, force_ascii=force_ascii)
        p2 = utils.full_process(s2, force_ascii=force_ascii)
    else:
        p1 = s1
        p2 = s2

    if not utils.validate_string(p1):
        return 0
    if not utils.validate_string(p2):
        return 0

    return ratio(p1, p2)

通過上面的例子可以看出,如果我們對QRatio、WRatio這些計(jì)分方式不滿意的話,完全可以自己實(shí)現(xiàn)了一個(gè)Ratio,將它做為extractOne的參數(shù),實(shí)現(xiàn)定制的返回結(jié)果。文章來源地址http://www.zghlxwxcb.cn/news/detail-422692.html

到了這里,關(guān)于python字符串模糊匹配,并計(jì)算匹配分?jǐn)?shù)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【字符串匹配】暴力匹配算法

    【字符串匹配】暴力匹配算法

    ? 暴力匹配算法,也稱為樸素字符串匹配算法,是一種簡單但不高效的字符串匹配方法。它的原理非常直觀,其主要思想是逐個(gè)字符地比較文本串和模式串,從文本串的每個(gè)可能的起始位置開始,依次檢查是否有匹配的子串。以下是暴力匹配算法的詳細(xì)原理: 1. 一個(gè)字一個(gè)

    2024年02月09日
    瀏覽(29)
  • 【數(shù)據(jù)結(jié)構(gòu)】數(shù)組和字符串(十四):字符串匹配1:樸素的模式匹配算法(StringMatching)

    【數(shù)據(jù)結(jié)構(gòu)】數(shù)組和字符串(十四):字符串匹配1:樸素的模式匹配算法(StringMatching)

    ??字符串(String)是由零個(gè)或多個(gè)字符(char)順序排列組成的有限序列,簡稱為串。例如 “good morning”就是由12個(gè)字符構(gòu)成的一個(gè)字符串。一般把字符串記作: S = ′ ′ a 0 a 1 … a n ? 1 ′ ′ S=\\\'\\\'a_{0} a_{1}…a_{n-1}\\\'\\\' S = ′′ a 0 ? a 1 ? … a n ? 1 ′′ ? ??其中S是串名,引號中

    2024年02月05日
    瀏覽(41)
  • Python計(jì)算字符串長度的函數(shù)

    1、使用內(nèi)置函數(shù)len 這是Python中一種常用的函數(shù),主要功能就是對字符串的長度進(jìn)行統(tǒng)計(jì),最后會(huì)返回一個(gè)字符串的實(shí)際長度,使用方法如下: 在示例中str就是一個(gè)要計(jì)算的字符串,它還可以是列表或者是字典等等。 2、使用for循環(huán) 使用for循環(huán)來統(tǒng)計(jì)字符串的長度時(shí),我們可以

    2024年02月13日
    瀏覽(24)
  • 字符串查找匹配算法

    字符串查找匹配算法

    字符串匹配(查找)是字符串的一種基本操作:給定帶匹配查詢的文本串S和目標(biāo)子串T,T也叫做模式串。在文本S中找到一個(gè)和模式T相符的子字符串,并返回該子字符串在文本中的位置。 Brute Force Algorithm,也叫樸素字符串匹配算法,Naive String Matching Algorithm。 基本思路就是將

    2024年02月14日
    瀏覽(27)
  • 【kmp算法】字符串匹配

    kmp算法解決的是字符串匹配的問題,具體來說假定我們要在主串s[ ] 中匹配模式串p[ ],找到匹配到的位置loc; 最自然的想法是暴力寫法 (BF)枚舉主串字符s[ i ] ,和模式串p[ j ]。一個(gè)一個(gè)匹配,如果匹配失敗,i指針回退回起點(diǎn),往前進(jìn)一位,再次進(jìn)行比較,知道匹配成功。

    2024年02月04日
    瀏覽(31)
  • 字符串匹配-KMP算法

    字符串匹配-KMP算法

    KMP算法,字符串匹配算法,給定一個(gè)主串S,和一個(gè)字串T,返回字串T與之S匹配的數(shù)組下標(biāo)。 在學(xué)KMP算法之前,對于兩個(gè)字符串,主串S,和字串T,我們根據(jù)暴力匹配,定義兩個(gè)指針,i指向主串S的起始,j指向字串T的起始,依次比較,如果 主串i位置的值等于子串j位置的值,

    2024年02月14日
    瀏覽(28)
  • 字符串匹配算法:KMP

    字符串匹配算法:KMP

    Knuth–Morris–Pratt(KMP)是由三位數(shù)學(xué)家克努斯、莫里斯、普拉特同時(shí)發(fā)現(xiàn),所有人們用三個(gè)人的名字來稱呼這種算法,KMP是一種改進(jìn)的字符串匹配算法,它的核心是利用匹配失敗后的信息,盡量減少模式串與主串的匹配次數(shù)以達(dá)到快速匹配的目的。它的時(shí)間復(fù)雜度是 O(m+n) 字

    2024年02月06日
    瀏覽(24)
  • 動(dòng)態(tài)規(guī)劃--通配字符串匹配

    1. 題目來源 鏈接:通配符匹配 來源:LeetCode 2. 題目說明 給定一個(gè)字符串 (s) 和一個(gè)字符模式 § ,實(shí)現(xiàn)一個(gè)支持 ‘?’ 和 ‘*’ 的通配符匹配。 ‘?’ 可以匹配任何單個(gè)字符。 ‘*’ 可以匹配任意字符串(包括空字符串)。 兩個(gè)字符串完全匹配才算匹配成功。 說明: s 可能為

    2024年02月14日
    瀏覽(35)
  • 一些常見的字符串匹配算法

    作者:京東零售?李文濤 字符串匹配在文本處理的廣泛領(lǐng)域中是一個(gè)非常重要的主題。字符串匹配包括在文本中找到一個(gè),或者更一般地說,所有字符串(通常來講稱其為模式)的出現(xiàn)。該模式表示為p=p[0..m-1];它的長度等于m。文本表示為t=t[0..n-1],它的長度等于n。兩個(gè)字符串都建

    2023年04月25日
    瀏覽(29)
  • Python三種計(jì)算字符串長度的函數(shù)分享

    Python三種計(jì)算字符串長度的函數(shù)分享

    ? Python三種計(jì)算字符串長度的函數(shù) 1、使用內(nèi)置函數(shù)len 這是Python中一種常用的函數(shù),主要功能就是對字符串的長度進(jìn)行統(tǒng)計(jì),最后會(huì)返回一個(gè)字符串的實(shí)際長度,使用方法如下: 1 2 str = \\\"hello python\\\" print ( len ( str )) 在示例中str就是一個(gè)要計(jì)算的字符串,它還可以是列表或者是字

    2024年02月04日
    瀏覽(33)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包