<p>我最近做了一个类似的任务,虽然我正在将新数据与数据库中的现有名称进行匹配,而不是在一个集合中查找重复项。名称匹配实际上是一项研究得很好的任务,有很多因素超出了匹配泛型字符串的考虑范围。</p>
<p>首先,我建议看一篇论文,<em>如何玩“名字游戏”:比较rafo和lhuilley的不同启发式方法的专利检索。发布的版本是<a href="http://www.sciencedirect.com/science/article/pii/S0048733309001528" rel="noreferrer">here</a>,PDF是免费的<a href="http://infoscience.epfl.ch/record/161961/files/Lhuillery%20RP2009b.pdf" rel="noreferrer">here</a>。作者提供了一个很好的总结,比较了许多不同的匹配策略。它们考虑三个阶段,称为解析、匹配和过滤。</p>
<p>解析包括应用各种清理技术。一些例子:</p>
<ul>
<li>标准化字体(例如,所有小写字母)</li>
<li>标点符号标准化(例如逗号后面必须有空格)</li>
<li>标准化空白(例如,将所有空白行转换为单个空格)</li>
<li>标准化重音字符和特殊字符(例如,将重音字母转换为等效的ASCII字符)</li>
<li>规范法律控制条款(例如,将“公司”转换为“公司”)</li>
</ul>
<p>在我的例子中,我将所有字母折叠为小写,将所有标点符号替换为空白,将重音字符替换为非重音对应字符,删除所有其他特殊字符,并从列表后面名称的开头和结尾删除法律控制术语。</p>
<p>匹配是对已解析名称的比较。这可以是简单的字符串匹配、编辑距离、Soundex或Metaphone、组成名称的单词集的比较、字母集或<em>n</em>-grams(长度为<em>n</em>的字母序列)的比较。gram方法实际上对名字很好,因为它忽略了单词的顺序,对“示例部门”和“示例部门”有很大帮助。事实上,使用类似<a href="http://en.wikipedia.org/wiki/Jaccard_index" rel="noreferrer">Jaccard index</a>的简单方法比较bigram(2-grams,字符对)非常有效。与其他一些建议相反,在名称匹配方面,Levenshtein距离是较差的方法之一。</strong></p>
<p>在我的例子中,我分两步进行匹配,首先比较分析的名称是否相等,然后使用Jaccard索引对其余的bigram集进行匹配。我没有实际计算所有名称对的所有Jaccard索引值,而是首先对给定大小的两组Jaccard索引的最大可能值设置一个界限,并且仅在该上限足够高到可能有用时计算Jaccard索引。大多数的名字对仍然很不相似,以至于它们不匹配,但这大大减少了进行比较的次数。</p>
<p>过滤是使用辅助数据从解析和匹配阶段拒绝误报。一个简单的版本是,看看匹配的名字是否对应于不同城市的企业,从而对应于不同的企业。这个例子可以在匹配之前应用,作为一种预过滤。之后可能会进行更复杂或耗时的检查。</p>
<p>我没怎么过滤。我检查了各国的公司,看它们是否相同,就是这样。数据中并没有那么多的可能性,一些时间限制排除了对额外数据的广泛搜索以增强过滤,而且无论如何,还有一个手动检查计划。</p>