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

如何解决在Python中进行字符串匹配时,有没有办法提高匹配性能?

我有一本非常大的词典,其中存储了大量的英语句子及其西班牙语翻译。当给定一个随机的英语句子时,我打算使用Python的fuzzywuzzy库在字典中找到最接近的匹配项。我的代码

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')

在现实生活中,sentencePairs词典非常大,至少存储了一百万个项目。因此,即使安装了python-Levenshtein来提供加速效果,也要花很长时间才能获得fuzzywuzzy的结果。 那么,有没有更好的方法来获得更好的性能呢?我的目标是在不到几秒钟的时间内甚至实时获得结果。

解决方法

如何提高性能

使用Levenshtein距离进行模糊匹配永远不会很快,但是您可以优化代码中的几件事:

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

  2. 即使在使用python-Levenshtein时,FuzzyWuzzy在很多地方也没有真正进行优化。您应该将其替换为RapidFuzz,该实现可以通过相似的接口实现相同的算法,但是主要是在C ++中实现的,并且还进行了一些其他算法上的改进,从而使其运行速度更快。

  3. 内部 a b c d <dbl> <dbl> <dbl> <dbl> 1 1 0.924 1 0.924 2 2 0.661 3 0.402 3 3 0.402 3 0.402 4 4 0.637 3 0.402 5 5 0.353 1 0.924 在默认情况下使用process.extractOne比较字符串。这是多个字符串匹配算法的组合。所以通过例如选择更快的算法fuzz.WRatio到process.extractOne可以提高性能。但是请记住,这会更改比较字符串的方式,因此根据您的数据,您可能不希望这样做。

使用1和2的实现

scorer=fuzz.ratio

使用1、2和3的实现

from rapidfuzz import process,utils
# english sentences are already lower cased
# and without special characters like question marks
sentencePairs = {'how are you':'¿Cómo estás?','good morning':'¡Buenos días!'}
query= 'How old are you?'
match,_ = process.extractOne(
   utils.default_process(query),sentencePairs.keys(),processor=None)
print(match,sentencePairs[match],sep='\n')

基准

为了提供一些时间比较,我生成了一百万个句子:

from rapidfuzz import process,utils,fuzz
# english sentences are already lower cased
# and without special characters like question marks
sentencePairs = {'how are you':'¿Cómo estás?',processor=None,scorer=fuzz.ratio)
print(match,sep='\n')

下表显示了我的计算机上不同解决方案所需的时间

import string
import random
random.seed(18)
sentencePairs = {
    ''.join(random.choice(string.ascii_lowercase + string.digits)
       for _ in range(15)
    ): "spanish text"
    for s in range(1000000)
}
query= 'How old are you?'
,

可能有更好的解决方案,但我想到的就是分区。

您可以创建26个不同的字典,每个字典代表一个英文字母。然后,您可以使用以相应字母开头的所有键加载所有这些词典。 例如。 adict,bdict ... zdict等 所以。 hdict将包含以h开头的Key的Key值。就像key =“你好吗?”

通过这种方式,您只需要查询与起始字母匹配的字典即可。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?