6

我需要删除包含许多段落的文本中的重复段落。

我使用类中的函数java.security.MessageDigest来计算每个段落的 MD5 哈希值,然后将这些哈希值添加到Set.

如果add()'ed 成功,则意味着最新的段落是重复的。

这种方式有风险吗?

除了String.equals(),还有其他方法吗?

4

5 回答 5

2

在散列之前,您可以规范化段落,例如删除标点符号、转换为小写和删除额外的空格。规范化后,仅存在差异的段落将获得相同的哈希值。

于 2013-04-05T08:21:22.610 回答
1

如果 MD5 散列尚未在集合中,则表示该段落是唯一的。但事实并非如此。因此,如果您发现哈希已经在集合中,您可能一个具有相同哈希值的非重复项。这不太可能发生,但您必须针对所有其他段落测试该段落才能确定。对于那个 String.equals 会做。

此外,您应该很好地考虑您所谓的唯一性(关于错字、空格、大写字母等),但任何方法都是如此。

于 2013-03-13T10:23:16.850 回答
1

无需计算 MD5 哈希,只需使用 aHashSet并尝试将字符串本身放入此集合中。这将使用该String#hashCode()方法计算字符串的哈希值并检查它是否已经在集合中。

public Set removeDuplicates(String[] paragraphs) {
    Set<String> set = new LinkedHashSet<String>();
    for (String p : paragraphs) {
        set.add(p);
    }
    return set;
}

使用LinkedHashSet偶数可以保持段落的原始顺序。

于 2013-03-13T10:28:14.327 回答
1

正如其他人所建议的那样,您应该意识到标点符号、空格、换行符等方面的微小差异可能会使您的哈希值在本质上相同的段落中有所不同。

也许您应该考虑一个不那么脆弱的指标,例如。余弦相似度非常适合匹配段落。

干杯,

于 2013-03-13T10:28:56.733 回答
0

我认为这是一个好方法。但是,有一些事情要记住:

  1. 请注意,计算哈希是一项繁重的操作。如果您不得不为数百万段重复它,这可能会使您的程序变慢。
  2. 即使以这种方式,您最终也可能会发现略有不同的段落(例如,有错别字)。如果是这种情况,您应该在计算哈希之前对段落进行规范化(将其转换为小写,删除多余的空格等)。
于 2013-03-13T10:22:48.083 回答