Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/341.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python中进行字符串匹配时,有没有提高匹配性能的方法?_Python_Performance_Fuzzywuzzy - Fatal编程技术网

在Python中进行字符串匹配时,有没有提高匹配性能的方法?

在Python中进行字符串匹配时,有没有提高匹配性能的方法?,python,performance,fuzzywuzzy,Python,Performance,Fuzzywuzzy,我有一本很大的字典,里面储存了大量的英语句子和它们的西班牙语翻译。当给出一个随机的英语句子时,我打算使用Python的fuzzyfuzzy库在字典中查找最接近的匹配项。我的代码: from fuzzywuzzy import process sentencePairs = {'How are you?':'¿Cómo estás?', 'Good morning!':'¡Buenos días!'} query= 'How old are you?' match = process.extrac

我有一本很大的字典,里面储存了大量的英语句子和它们的西班牙语翻译。当给出一个随机的英语句子时,我打算使用Python的fuzzyfuzzy库在字典中查找最接近的匹配项。我的代码:

from fuzzywuzzy import process
sentencePairs = {'How are you?':'¿Cómo estás?', 'Good morning!':'¡Buenos días!'}
query= 'How old are you?'
match = process.extractOne(query, sentencePairs.keys())[0]
print(match, sentencePairs[match], sep='\n')
在现实生活中,
语句对
字典将非常大,至少存储了一百万个条目。因此,即使安装了python Levenshtein以提供加速,使用FuzzyFuzzy获得结果也需要很长时间。
那么,有没有更好的方法来实现更好的性能呢?我的目标是在不到几秒钟的时间内得到结果,甚至是实时得到结果。

可能有更好的解决方案,但在我的脑海中,我可以想到分区

您可以创建26个不同的字典,每个字典代表一个英语字母表。然后你可以加载所有这些字典和所有以字母表开头的键。 例如,adict、bdict。。。zdict等。 所以hdict将包含以h开头的键的键值。比如key=“你好吗?”

这样,您只需要查询与起始字母表匹配的字典。

提高性能的方法 使用Levenshtein距离的模糊匹配永远不会超快速,但您的代码中有一些东西可以优化:

  • 将字符串和列表传递给process.extractOne时,它将通过将字符串小写、删除非字母数字字符和修剪空白来预处理这些字符串。由于您每次重复使用相同的English:Spanish映射,因此您应该提前进行一次预处理

  • 即使在使用python时,Levenshtein FuzzyWzzy在很多地方也没有得到真正的优化。你应该用类似的接口来代替它,但是大多数都是用C++实现的,并且还有一些额外的算法改进,使它更快。
  • 默认情况下,内部
    process.extractOne
    使用
    fuzz.WRatio
    比较字符串。这是多个字符串匹配算法的组合。因此,通过将例如
    scorer=fuzz.ratio
    传递给process.extractOne来选择更快的算法,可以提高性能。但是请记住,这会改变字符串的比较方式,因此根据您的数据,您可能不希望这样做

  • 利用1和2实现
    来自rapidfuzz导入过程,utils
    #英语句子已经是小写了
    #没有问号之类的特殊字符
    句子对={‘你好’:‘你好吗?’,‘早上好’:‘布宜诺斯艾利斯!’
    query='你多大了?'
    匹配,u=process.extractOne(
    utils.default_进程(查询),
    sentencePairs.keys(),
    处理器=无)
    打印(匹配,句子对[match],sep='\n')
    
    利用1、2和3实现
    来自rapidfuzz导入过程、utils、fuzz
    #英语句子已经是小写了
    #没有问号之类的特殊字符
    句子对={‘你好’:‘你好吗?’,‘早上好’:‘布宜诺斯艾利斯!’
    query='你多大了?'
    匹配,u=process.extractOne(
    utils.default_进程(查询),
    sentencePairs.keys(),
    处理器=无,
    记分器=模糊比率)
    打印(匹配,句子对[match],sep='\n')
    
    基准 为了提供一些时间比较,我生成了一百万个句子:

    导入字符串
    随机输入
    随机种子(18)
    句子对={
    ''.join(random.choice(string.ascii_小写+string.digits)
    适用于范围内的(15)
    ):“西班牙文文本”
    适用于范围内的s(1000000)
    }
    query='你多大了?'
    
    下表显示了不同解决方案在我的计算机上需要多长时间

    |实现|运行时|
    |------------------------------------------|----------------|
    |您当前的实现| 18.98秒|
    |利用1和2 | 1.4秒实现|
    |利用1、2和3 | 0.4秒实施|
    
    使用此解决方案,您将丢失对第一个字符的“模糊”搜索。不过,这仍然是一个有效的选项。请注意,您在这里实际上并没有按预期使用
    dict
    ,您还可以使用元组列表,或者两个单独的列表,我在代码中找不到
    fuzz.ratio
    fuzz.WRatio
    。您的意思是使用它们来循环所有
    sentenPairs
    键,而不是
    process.extractOne()
    ,并且使用
    fuzz.ratio
    时需要0.4秒?prcess.extractOne支持记分器参数来更改其使用的字符串匹配算法。我更新了答案,使之更清楚。关于
    utils.default\u进程
    处理器
    ,我可以只使用
    match、=process.extractOne(query,sentencePairs.keys(),scorer=fuzz.ratio)
    而不是
    match、=process.extractOne(utils.default\u进程(query),sentencePairs.keys(),处理器=无,记分器=模糊比率)
    ?这两行代码之间似乎没有区别,根据我的测试,执行时间基本相同。我还检查了,仍然找不到任何差异。utils.default_进程正在预处理字符串(小写,删除非字母数字字符,例如问号和修剪空白)。因此,当您不需要/不想要此项时,您可以将其省略(例如,字符串“您多大岁数?”转换为“您多大岁数”)