Java中的模糊匹配重复

时间:2014-05-25 07:58:44

标签: java pattern-matching fuzzy-search

我在Java中有List<String[]>个客户记录(来自数据库)。我知道从手动眼球看25%+是重复的数据。

重复的内容远非精确。有时他们有不同的拉链,但名称和地址相同。其他时候地址完全丢失等等......

经过一天的研究;关于如何开始攻击这个问题我还是很难过吗?

我应该用Google搜索描述这个区域的“术语”(从Java角度解决这个问题)?而且我不认为那里有fuzzymatch.jar让一切变得简单易行?

2 个答案:

答案 0 :(得分:2)

我之前为匹配地点信息和人员信息做了类似的系统。这些是具有许多特征的复杂对象,并且确定两个不同的对象是否描述相同的地方或人是棘手的。这样做的方法是将其分解为基本要素。

以下是您可以做的一些事情:

0)如果是oneoff,请将数据加载到openrefine并以交互方式修复。最大限度地解决了您的问题,最小化它将显示您可能的匹配位置。

1)有几种方法可以比较字符串。基本上,他们在产生消极和错误匹配的可靠性方面存在差异。否定匹配是指匹配时它不应该匹配。积极匹配是它应该匹配的时间。字符串等于不会产生负面匹配,但由于轻微的变化会错过很多潜在的匹配。 Levenstein的因素稍微好一点。 Ngrams产生了很多匹配,但其中很多都是假的。还有一些算法,请查看例如openrefine代码,用于查找比较和聚类字符串的各种方法。 Lucene在其分析器框架中实现了很多这样的东西,但是如果你对它的设计不是很熟悉的话,它就像是一个野兽。

2)将比较过程与确定您是否匹配的过程分开。我过去所做的是使用简单的数字分数来限定我的比较,例如这个字段完全匹配(100),但该字段是部分匹配(75),该字段根本不匹配。得到的合格比较矢量,例如, (100,75,0,25)可以与定义完美或部分匹配标准的参考向量进行比较。例如,如果名字,姓氏和街道匹配,则无论其他字段如何,这两条记录都是相同的。或者如果phonenumbers和姓氏匹配,那也是有效的匹配。您可以将这样的完美匹配编码为矢量,然后将其与比较矢量进行比较,以确定它是匹配,不匹配还是部分匹配。这是机器学习所做的手动版本,即提取特征向量,然后建立概率模型,其中向量表示来自参考数据的内容。手动完成,可以解决简单问题。

3)使用您知道匹配或不匹配的测试用例构建参考数据集,并根据该参考集评估算法。通过这种方式,当您调整时,您将知道何时改善事物或使事情变得更糟莱文斯坦或其他什么因素。

答案 1 :(得分:1)

Jilles&#39;答案很棒,来自经验。我还必须努力清理大杂乱的桌子,遗憾的是当时我对我的选择知之甚少(最后我使用了Excel和很多自动过滤器)。希望我对OpenRefine了如指掌。

但是如果你到了必须编写自定义代码来执行此操作的程度,我想就如何做出建议:列总是一样的,对吧?例如,第一个String总是键,第二个是名字,第六个是邮政编码,第十个是传真号码等?

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

这样的东西
class CustomerRow {
    public final String id;
    public final String firstName;
    // ...

    public CustomerRow(String[] data) {
        id = data[0];
        // ...
}

如果您知道要总是要过滤掉垃圾值,您还可以在构造函数中包含一些验证代码。

(请注意,您基本上是在做ORM会自动执行的操作,但是开始使用ORM可能比编写Record类型更有用。)

然后你实现了一些Comparator<CustomerRow>只能查看特定字段,或者用模糊术语定义相等性(编辑距离算法会派上用场),或者做特别的排序

Java对对象使用稳定的排序,因此要按例如排序name,then address,then key,你只需要进行各种排序,但请按相反顺序选择比较器。

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