Java中的模糊匹配副本

Java中的模糊匹配副本,java,pattern-matching,fuzzy-search,Java,Pattern Matching,Fuzzy Search,我有一个Java客户记录的列表(来自数据库)。通过手动查看数据,我知道25%以上的数据是重复的 不过,复制品远非精确。有时他们有不同的拉链,但相同的名字和地址。其他时候地址完全丢失,等等 经过一天的研究;对于如何开始解决这个问题,我仍然感到困惑 我应该在谷歌上搜索哪些术语来描述这个领域(从Java角度解决这个问题)?我不认为有fuzzymatch.jar让一切变得简单 我以前做过类似的系统来匹配地点信息和人员信息。这些是具有许多特征的复杂对象,要弄清楚两个不同的对象是描述同一个地方还是描述同一个

我有一个Java客户记录的
列表(来自数据库)。通过手动查看数据,我知道25%以上的数据是重复的

不过,复制品远非精确。有时他们有不同的拉链,但相同的名字和地址。其他时候地址完全丢失,等等

经过一天的研究;对于如何开始解决这个问题,我仍然感到困惑


我应该在谷歌上搜索哪些术语来描述这个领域(从Java角度解决这个问题)?我不认为有
fuzzymatch.jar
让一切变得简单

我以前做过类似的系统来匹配地点信息和人员信息。这些是具有许多特征的复杂对象,要弄清楚两个不同的对象是描述同一个地方还是描述同一个人是很困难的。要做到这一点,就要把它分解到最基本的部分

以下是您可以做的几件事:

0)如果这是一次性的,请将数据加载到openrefine中,并以交互方式进行修复。最大限度地解决您的问题,最小限度地,它将显示您的可能匹配的地方

1) 有几种方法可以比较字符串。基本上,它们在产生否定匹配和错误匹配方面的可靠性不同。负匹配是指在不应该匹配的情况下匹配。积极匹配是指它应该匹配并且确实匹配的时间。String equals不会产生负匹配,但会由于细微的变化而错过许多潜在的匹配。小因子的Levenstein稍微好一点。Ngrams产生了很多匹配,但其中很多都是错误的。还有一些算法,比如openrefine代码,可以找到比较和聚类字符串的各种方法。Lucene在其analyzer框架中实现了很多这方面的功能,但如果您对其设计不是很熟悉,那么它就有点难以使用

2) 将比较材料的过程与确定是否匹配的过程分开。我过去所做的是用一个简单的数字分数来限定我的比较,例如,该字段完全匹配(100),但该字段是部分匹配(75),而该字段根本不匹配。合格比较的结果向量,例如(100,75,0,25),可以与定义完美或部分匹配标准的参考向量进行比较。例如,如果名字、姓氏和街道匹配,则无论其余字段如何,这两条记录都是相同的。或者,如果电话号码和姓氏匹配,这也是一个有效的匹配。您可以将这些完美匹配编码为向量,然后简单地将其与比较向量进行比较,以确定它是匹配、不是匹配还是部分匹配。这是机器学习的一种手动版本,它提取特征向量,然后建立一个概率模型,从参考数据中确定哪些向量意味着什么。手动操作可以解决简单的问题


3) 用已知匹配或不匹配的测试用例建立一个参考数据集,并根据该参考集评估算法。这样,当你调整时,你就会知道你是在改进事情还是让事情变得更糟,例如,莱文斯坦或其他什么因素。

吉利斯的答案很好,来自经验。我还不得不清理凌乱的大桌子,遗憾的是,当时我对自己的选择知之甚少(我最终使用了Excel和许多自动过滤器)。要是我知道OpenRefine就好了

但是,如果您需要编写自定义代码来完成这项工作,我想提出一个建议:列总是相同的,对吗?例如,第一个字符串总是键,第二个是名字,第六个是邮政编码,第十个是传真号码,等等

假设没有不合理的字段数量,我将从一个自定义记录类型开始,它将每个DB字段作为成员,而不是数组中的一个位置。差不多

class CustomerRow {
    public final String id;
    public final String firstName;
    // ...

    public CustomerRow(String[] data) {
        id = data[0];
        // ...
}
如果您知道存在总是要过滤掉的垃圾值,那么还可以在构造函数中包含一些验证代码

(请注意,您基本上是在做ORM会自动完成的事情,但是开始使用ORM可能比编写记录类型要复杂得多。)

然后,您将实现一些
比较器
s,它们只查看特定字段,或者用模糊术语定义相等性(编辑距离算法将在这里派上用场),或者进行特殊排序

Java对对象使用稳定的排序,因此要按名称、地址、键等进行排序,您只需执行每个排序,但选择的比较器顺序相反


另外,如果您可以访问实际的数据库,并且它是一个真正的关系数据库,我建议您尽可能将一些搜索作为查询。如果您需要在Java对象和DB之间来回切换,那么使用ORM可能是一个不错的选择。

编辑距离算法,如Levenshtein距离或Hamming距离,以及它们的派生。Lucerne和solr是用Java编写的,并且是用于模糊匹配的功能工具,除此之外,Levenshtein只会处理一根弦?不是一组字符串吗?