假设我有一个类

public class Audio
{
    public string artist   { get; set; }
    public string title    { get; set; }
    // etc.
}

现在,我想通过相似性(不是完全匹配)条件来过滤此类音频列表中的重复项。基本上,这是勒文斯泰因距离,并通过弦的总长度进行阈值校正。问题是,关于IEqualityComparer的一般提示是“始终实现GetHashCode和Compare”。我显然无法计算GetHashCode中字符串之间的距离,因为它根本不是比较方法。但是,在这种情况下,即使是相似的音频也会返回不同的哈希值,而Distinct()会将其视为不同的对象,并且不会触发compare()方法。

我试图强制GetHashCode始终返回0,所以在collection中为每个对象调用Compare,但这很慢。所以,最后,一个问题是:.net可以直接使用.net做任何事情吗?还是应该搜索一些好的过滤算法?

最佳答案

我建议(首先)不要使用 Distinct GetHashCode

GetHashCode 对于您的情况过于严格(如@Gabe所指出的那样)。
您可以做的是:

  • 承认您将必须使用Levenshtein
  • 比较实例对的整个三角形(O(n ^ 2)复杂度)
  • 尝试使用本书中的所有技巧来优化该效果:如何计算从空字符串到当前一种声音(即Audio的每个实例,以及两个字符串属性可能分别)的 Levenshtein距离?

  • 最终(可能有人会说)得到了一个好东西 GetHashCode
    但是您不能像 GetHashCode 那样使用它,而应该这样使用:
    bool AreSimilar(Audio me, Audio you) {
      int cheapLevenshtein = Math.Abs(me.AbsoluteQuasiLevenshtein - you.AbsoluteQuasiLevenshtein);
    
      if (cheapLevenshtein < THRESHOLD) {
    
        int expensiveLevenshtein = Audio.LevenshteinBetween(me, you);
        var result = (expensiveLevenshtein < LIMIT);
        return result;
    
      } else
        return false;
    }
    

    然后,您将获得更好或更糟的算法。这只是一个想法,当然:您不能使用Distinct()。如果愿意,您可以编写自己的扩展方法,从用户程序员的角度来看,使整个过程看起来不错。

    是的, AbsoluteQuasiLevenshtein 在诸如“ab”和“zy”之类的东西上是相等的,但在“ab”和“blahblahblahblah”之间却有很大的不同,至少您会优化一些东西。 ( GetHashCode + 不同的方法提出了另一个问题- GetHashCode 的严格性)。

    关于c# - .net Distinct()和复杂条件,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15055473/

    10-12 16:50