【发布时间】:2014-06-11 20:51:48
【问题描述】:
我正在寻找一个模糊搜索 JavaScript 库来过滤数组。我尝试过使用fuzzyset.js 和fuse.js,但结果很糟糕(您可以在链接页面上尝试演示)。
在阅读了一些关于 Levenshtein 距离的内容后,我觉得它与用户在键入时所寻找的内容的近似值很差。对于不知道的人,系统会计算出使两个字符串匹配需要多少次插入、删除和替换。 p>
在 Levenshtein-Demerau 模型中修复的一个明显缺陷是 blub 和 boob 被认为与 bulb 相同(每个都需要两个替换)。然而,很明显 bulb 与 blub 比 boob 更相似,而且我刚才提到的模型通过允许 换位。
我想在文本完成的上下文中使用它,所以如果我有一个数组 ['international', 'splint', 'tinder'],并且我的查询是 int,我认为 international 应该排名比 splint 更高,尽管前者的得分(更高=更差)为 10,而后者为 3。
所以我正在寻找(如果它不存在将创建)是一个执行以下操作的库:
- 加权不同的文本操作
- 根据每个操作在单词中的出现位置不同地加权每个操作(早期操作比后期操作成本更高)
- 返回按相关性排序的结果列表
有没有人遇到过这样的事情?我意识到 StackOverflow 不是要求软件推荐的地方,但上面隐含的(不再是!)是:我是否以正确的方式考虑这个?
编辑
我在该主题上找到了good paper (pdf)。一些注释和摘录:
仿射编辑距离函数为插入或删除序列分配相对较低的成本
Monger-Elkan 距离函数 (Monge & Elkan 1996),它是 Smith-Waterman 距离函数 (Durban et al. 1998) 的仿射变体,具有特定的成本参数
对于Smith-Waterman distance (wikipedia),“Smith-Waterman 算法不是查看总序列,而是比较所有可能长度的片段并优化相似性度量。”这是 n-gram 方法。
不基于编辑距离模型的大体相似的指标是 Jaro 公制 (Jaro 1995; 1989; Winkler 1999)。在记录链接文献中,使用这种方法的变体获得了良好的结果,该方法基于两个字符串之间公共字符的数量和顺序。
Winkler (1999) 的变体也使用最长公共前缀的长度 P
(似乎主要用于短字符串)
出于文本完成的目的,Monger-Elkan 和 Jaro-Winkler 方法似乎最有意义。 Winkler 对 Jaro 度量的添加有效地加重了单词的开头。 Monger-Elkan 的仿射方面意味着完成一个单词的必要性(它只是一个添加序列)不会太不喜欢它。
结论:
TFIDF 排名在几个基于令牌的距离中表现最好 Monge 和 Elkan 提出的调整仿射间隙编辑距离度量在几个指标中表现最好 字符串编辑距离指标。出奇的好距离 metric 是一种快速启发式方案,由 Jaro 提出,后来由 Winkler 扩展。 这几乎和 Monge-Elkan 方案一样有效,但是 快了一个数量级。 一种将 TFIDF 方法与 Jaro-Winkler 将替换在 TFIDF 与基于 Jaro- 的近似令牌匹配 温克勒方案。平均而言,这种组合的性能略好于 Jaro-Winkler 或 TFIDF,偶尔也会表现得更好。它的性能也接近于几个最佳指标的学习组合 本文考虑。
【问题讨论】:
-
好问题。我正在寻找类似的东西,但具有相同的字符串比较注意事项。你有没有找到/构建你的字符串比较的 javascript 实现?谢谢。
-
@nicholas 我只是在 github 上分叉了模糊集.js 以解决较小的查询字符串,虽然它不考虑加权字符串操作,但结果对于我预期的字符串补全应用来说非常好。见the repo
-
谢谢。我会试试看。我还发现了这个字符串比较函数:github.com/zdyn/jaro-winkler-js。似乎也很好用。
-
@michaelday 这没有考虑错别字。在演示中,输入
krole不会返回Final Fantasy V: Krile,尽管我希望这样。它要求查询中的所有字符在结果中以相同的顺序出现,这是相当短视的。似乎获得良好模糊搜索的唯一方法是拥有一个常见拼写错误的数据库。
标签: javascript regex pattern-matching string-matching fuzzy-search