我正在寻找一个模糊搜索 JavaScript 库来过滤数组。我试过使用Fuzzyset.js和fuse.js,但结果很糟糕(你可以在链接页面上尝试一些演示)。
在对 Levenshtein distance 进行了一些阅读之后,我觉得它对用户在键入时正在寻找的内容的近似值很差。对于那些不知道的人,系统会计算需要多少次插入、删除和替换才能使两个字符串匹配。
Levenshtein-Demerau 模型中修复的一个明显缺陷是,blub和boob都被认为与bulb相似(每个都需要两次替换)。然而,很明显,bulb比boob更类似于blub,我刚才提到的模型通过允许换位来识别这一点。
我想在文本完成的上下文中使用它,所以如果我有一个数组['international', 'splint', 'tinder']
,并且我的查询是int,我认为国际应该比splint排名更高,即使前者的分数(更高=更差)为 10与后者的 3.
所以我正在寻找(如果它不存在就会创建)是一个执行以下操作的库:
- 加权不同的文本操作
- 根据它们在单词中出现的位置对每个操作赋予不同的权重(早期操作比后期操作成本更高)
- 返回按相关性排序的结果列表
有没有人遇到过这样的事情?我意识到 StackOverflow 不是要求软件推荐的地方,但上面隐含的(不再是!)是:我是否以正确的方式思考这个问题?
编辑
我找到了一篇关于这个主题的好论文 (pdf)。一些笔记和摘录:
仿射编辑距离函数为插入或删除序列分配相对较低的成本
Monger-Elkan 距离函数 (Monge & Elkan 1996),它是 Smith-Waterman 距离函数 (Durban et al. 1998) 的仿射变体,具有特定的成本参数
对于Smith-Waterman 距离(维基百科),“Smith-Waterman 算法不是查看整个序列,而是比较所有可能长度的片段并优化相似性度量。” 这是n-gram方法。
一个不基于编辑距离模型的广泛相似的度量是 Jaro 度量(Jaro 1995;1989;Winkler 1999)。在记录链接文献中,使用这种方法的变体已经获得了良好的结果,该方法基于两个字符串之间公共字符的数量和顺序。
由 Winkler (1999) 提出的一个变体也使用最长公共前缀的长度 P
(似乎主要用于短字符串)
对于文本补全,Monger-Elkan 和 Jaro-Winkler 方法似乎最有意义。Winkler 对 Jaro 度量的添加有效地加重了单词开头的权重。并且 Monger-Elkan 的仿射方面意味着完成一个单词的必要性(这只是一系列添加)不会太不喜欢它。
结论:
TFIDF 排名在几个基于标记的距离度量中表现最好,Monge 和 Elkan 提出的调整仿射间隙编辑距离度量在几个字符串编辑距离度量中表现最好。一个非常好的距离度量是快速启发式方案,由 Jaro 提出,后来由 Winkler 扩展。这几乎与 Monge-Elkan 方案一样有效,但要快一个数量级。结合 TFIDF 方法和 Jaro-Winkler 的一种简单方法是用基于 Jaro-Winkler 方案的近似标记匹配替换 TFIDF 中使用的精确标记匹配。这种组合的平均性能略好于 Jaro-Winkler 或 TFIDF,有时性能要好得多。它的性能也接近于本文中考虑的几个最佳指标的学习组合。