Java中的模糊字符串搜索库


71

我正在寻找一种用于模糊字符串搜索的高性能Java库。

有很多算法可以查找相似的字符串,Levenshtein距离,Daitch-Mokotoff Soundex,n-gram等。

存在哪些Java实现?对他们有利有弊?我知道Lucene,还有其他解决方案还是Lucene最好?

我找到了这些,有没有人有经验?

Answers:


40

Commons Lang实现了Levenshtein距离

Commons Codec具有soundexmetaphone的实现。


4
无法评论其他内容,但我发现公共语言的Levenshtein距离对于模糊相等性检查(而不是模糊包含)有用。不幸的是,您仍然必须编写自己的算法来使用它。这仍然需要一些努力才能正确执行(您必须在源字符串中匹配不同的长度)并具有良好的性能(bitap可能比仅使用Levenshtein距离可以写的速度要快得多)。
Henno Vermeulen

@HennoVermeulen,如果您找到任何解决方案,可以与我们分享吗?Java中bitap的任何实现?
hereForLearing '16

我对这个问题的答案包含一个Java实现的链接(实际上,这是我在搜索“ Java bitap”时找到的第一个)
Henno Vermeulen

1
对于那些正在寻找简单的模糊搜索而实际上从字符串而不是分数返回匹配的子字符串的人,这里有一个要点:gist.github.com/shathor/8ad04d8923d6c07fd2f4a06e9543bebf。编辑:@sukhmel我已经更新了此评论中的链接(删除了旧的链接)。如果再次发生,要点应该在我的仓库中
Terran

14

如果您主要是比较短字符串,并且想要一些轻便且轻便的东西,则可以使用移植到Java的著名python算法Fuzzywuzzy 。

您可以在此处了解更多信息


2
刚有了使用Fuzzywuzzy的非常积极的经验。将250,000+个对象集合中的几个字符串与30,000个对象进行了比较。模糊匹配是有效的,并且api是用户友好的。
吉尔伯特·阿里纳斯·匕首

很棒的图书馆,我将其与我们当前的Android项目集成在一起,初步结果非常有希望
A.Alqadomi

1
请注意,Python和Java版本均已获得GPL许可。
阿索尔

1
由于无论我在哪里搜索都找不到它,因此导入它的方法是(一旦在类路径上有jar)import me.xdrop.fuzzywuzzy.*;
Siddhartha

11

您可以使用Apache Lucene,但是根据使用情况,这可能太重了。对于非常简单的模糊搜索,使用起来可能有点复杂,并且(如果我错了,请更正我)它需要您建立索引。

如果您需要一个简单的在线(不维护索引)算法,则可以使用模糊Bitap算法。我在这里找到了Java实现。它的代码适合于一个相对简短的方法,带有几乎不言自明的签名:

public static List<Integer> find(String doc, String pattern, int k)

Apache CommonsStringUtils具有用于模糊字符串匹配的Levenshtein算法的实现。可以将其视为的模糊版本String.equals,Bitap类似于的模糊版本,String.indexOf仍然使用Levenshtein距离度量。通常,与天真地使用Levenshtein来比较搜索模式与每个可能匹配的子字符串相比,效率更高。

注意事项

  • 对于相对较小的字母,例如纯ASCII,Bitap算法似乎最有用。实际上,我链接到的Simon Watiau版本会抛出ArrayIndexOutOfBoundsException非ASCII字符(> = 128),因此您必须将其过滤掉。
  • 我尝试在应用程序中使用Bimap来按名称搜索人员的内存列表。我发现Levenhstein距离2会产生太多误报。Levenhstein距离为1会更好,但无法检测到您在交换两个字母(例如“ William”和“ Willaim”)时出现的错字。我可以想到几种解决方法,例如

    1. 仅当精确搜索未找到匹配项时才进行模糊搜索(并向用户显示有关此信息)
    2. 调整Bitap以使用Damerau-Levenshtein距离(其中交换具有距离1而不是2)。根据Wikipedia的说法,这是可能的,但是我找不到Java中的现有实现。
    3. 而不是“包含”执行“ startsWith”。在模糊搜索工具包含Damerau -莱文斯坦的前缀版本,但它给了我一个ArrayIndexOutOfBoundsException
    4. 调整算法以引入搜索结果排名,其中精确匹配得分更高

    如果您要执行2或4,则最好还是使用像Lucene这样的适当的全文本搜索库。

  • 有关模糊搜索的更多信息,请参见此博客。它的作者还用Java创建了一个称为的实现BitapOnlineSearcher,但要求您将其java.io.Reader与Alphabet类一起使用。它的Javadoc是用俄语编写的。

有没有一种方法可以使Bitap搜索仅搜索具有相同字母数的单词,例如,如果我搜索k = 2的名称接受Namo和Mamo但不接受Nam的话?
hereForLearing '16

8

您可能需要SimMetrics:http : //sourceforge.net/projects/simmetrics/

它有几种算法可以计算各种编辑距离。

Lucene是一个非常强大的全文本搜索引擎,但是FT搜索与模糊字符串匹配并不完全相同(例如,给定一个字符串列表,找到与某些候选字符串最相似的字符串)。


2
simmetrics似乎是GPL v2,因此与商业开发的软件不兼容。
丹·海伍德

GitHub上有一个“重写”,有一个开放的问题来解决许可问题:github.com/Simmetrics/simmetrics/issues/5
peater

@DanHaywood从版本3.2.3开始,许可已更改为Apache版本2.0
MP Korstanje

1
@pppeater(版本3.2.3以上)已将许可证更改为Apache版本2.0
MP Korstanje 2015年


2

您可以尝试Completely库,该库依赖于文本预处理来创建内存中索引,以有效回答大型数据集中的(模糊)搜索。与Lucene和其他功能齐全的文本搜索库不同,该API很小,易于上手。



1

我认为,Apache Lucene是唯一的方法。我不知道有什么更好的搜索库。

Apache Lucene™是完全用Java编写的高性能,全功能的文本搜索引擎库。它是一项适用于几乎所有需要全文搜索的应用程序的技术,尤其是跨平台。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.