2013-02-24 4 views
5

私は今、私は類似性(ないEXACTマッチ)条件によって、オーディオのリストの重複をフィルタリングするクラスに.NET(個別)と複雑なconditons

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

を持っていると仮定します。基本的には、弦全体の長さによるスレッショルド修正を伴うLevenstein距離です。問題は、IEqualityComparerについての一般的なヒントは「常にGetHashCodeとCompareの両方を実装する」ことです。私は明らかにGetHashCodeの文字列間の距離を計算することはできません。なぜなら、これは比較メソッドではないからです。しかし、この場合でも同様のオーディオでさえ異なるハッシュを返し、Distinct()はそれを別のオブジェクトとして扱い、compare()メソッドは起動しません。

GetHashCodeが常に0を返すようにしたので、コレクション内の各オブジェクトへの比較が呼び出されましたが、これは遅いです。だから最後に、質問:ボックスの外で.netを使ってできることは何か、またはフィルタリングのための良いアルゴリズムを検索する必要がありますか?

+8

「Distinct」を乱用している可能性があります。例えば、 'ab'は' bc'の複製であり、 'bc'は' cd'の複製であると考えるかもしれませんが、 'ab'は' cd'の複製であるとは考えません。これにより、「Distinct」はあなたのためには機能しません。 – Gabe

+0

ありがとう、ガベ、私はそれについて考えなかった。私は検索アルゴリズムについての良い本を読むだけでよいはずです。 – Tommi

+0

オブジェクトの静的で長いリストがある場合 - BKツリーを見て、あなたが達成しようとしているものを多く手助けすることができます。私はF#の実装を書いたことがありますが、それはあなたの目標にはかなり役立ちます。任意のオブジェクトをその中に格納し、セレクタ関数によって任意のプロパティのlevenshteinと比較することができます。興味があれば、コードをbitbucketにアップロードできます。 – rkrahl

答えて

3

私は個別またはGetHashCodeメソッドを使用していない(最初のすべての)お勧めします。

GetHashCodeはあなたのケースでは厳しいです(@Gabeが完全に指摘したように)。 何をあなたができることです:レーベンシュタイン

  • を使用してインスタンスのペアの

    1. は、あなたが全体の三角形(O(N^2)複雑さ)を比較する必要があると認めるには、内のすべてのトリックを使用していることを最適化するようにしてください本:どのように計算する空の文字列から現在の1つの音(これは、オーディオの各インスタンスごと、おそらく両方の文字列のプロパティのためにおそらく)Levenshteinの距離ですか?くそ良いGetHashCodeメソッドで(1が言うかもしれない)終わる可能性

    。 しかし、あなたは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 + Distinctのアプローチでは、別の問題が発生しました - 厳密さはGetHashCodeです)。シンプルな "C#の相互運用性" 層とC#の例でBKTreeため

  • +0

    私はあなたのポイントを得る。最も簡単な 'AbsoluteQuasiLevenshtein'は文字列の長さですか? – Tommi

    +0

    確かに。そして、そうでなければ、より良いもの(特にあなたの場合)を見つけることはあなた次第です。あなたが成功した場合、共有してください:) –

    1

    コードは、ここにある:

    https://bitbucket.org/ptasz3k/bktree

    これは、VS 2012ソリューションです。

    すべてのオブジェクトからツリーを作成し、セレクタ関数(x => x.Key)を渡します。たとえば、ToLowerInvariant()を実行すると、指定されたキーとlevenshtein distanceを検索し、ツリーはすべての一致するオブジェクトを返します。

    私が正しくあなたの問題を理解してあれば、:

    var bk = BKTree.CSharp.CreateBK(x => x.artist, audios); 
    var allArtists = audios.Select(x => x.artist); 
    var possibleDuplicates = allArtists.Select(x => new 
        { Key = x, Similiar = BKTree.CSharp.FindInBk(bk, x, treshold).ToList()); 
    

    は、この情報がお役に立てば幸いです。

    +0

    いいね、私はすぐにそれを試してみましょう、ありがとう。 – Tommi

    +0

    f#コードを見れば、独自の距離関数 'key - > int(またはより具体的には、比較を実装する任意の数値型)を使用してbk treeをパラメータ化できることに気づくでしょう。ここで' keyは 'object_stored 。私はC#でそれを許可しませんでしたが、それは非常に簡単なことです。しかし、1つの条件があり、それはbk-treesに特有のものです。あなたの距離関数はメートル法でなければなりません。あなたのカスタム関数が正式に証明されることはあなたのケースでは難しいと思います。申し訳ありませんが、私はもっと助けることができませんでした。あなたの探求に幸運とそれを完了するときにいくつかの情報を与える! – rkrahl

    関連する問題