web-dev-qa-db-ja.com

テキスト差分アルゴリズム

2つのテキストファイルを比較してそれらの違いを強調し、(さらに良い!)意味のある方法でそれらの違いを計算できるアルゴリズムが必要です(たとえば、2つの類似ファイルは2つの異なるファイルよりも高い類似スコアを持ち、「類似」という単語が必要です)通常の用語で定義されます)。実装は簡単に聞こえますが、そうではありません。

実装はc#またはpythonにすることができます。

ありがとう。

43
Graviton

Pythonには、他の人が示唆しているように、 difflib があります。

difflibSequenceMatcher クラスを提供します。これは、類似度を与えるために使用できます。関数の例:

def text_compare(text1, text2, isjunk=None):
    return difflib.SequenceMatcher(isjunk, text1, text2).ratio()
25
tzot

NeilFraserのコードと記事をご覧になることをお勧めします。

google-diff-match-patch

現在、Java、JavaScript、C++、Pythonで利用できます。言語に関係なく、各ライブラリは同じAPIと同じ機能を備えています。すべてのバージョンには、包括的なテストハーネスもあります。

Neil Fraser:Diff Strategies -理論と実装に関する注意事項

30
aku

difflib を見てください。 (Python)

これにより、さまざまな形式で差分が計算されます。次に、コンテキスト差分のサイズを、2つのドキュメントの違いの尺度として使用できますか?

23
Douglas Leeder

Bazaar には、 patience diff (そのページのコメントに詳細があります)と呼ばれる代替の差分アルゴリズムが含まれています。これは、従来の差分アルゴリズムよりも優れていると言われています。 Bazaarディストリビューションのファイル「patiencediff.py」は、単純なコマンドラインフロントエンドです。

10
Daniel James

私の現在の理解では、Shortest Edit Script(SES)の問題に対する最善の解決策は、Hirschberg線形空間の改良を使用したMyersの「ミドルスネーク」法です。

マイヤーズアルゴリズムは次のように説明されています。

E.マイヤーズ、 `ʻAn O(ND)差分アルゴリズムとそのバリエーション、 ''
Algorithmica 1、2(1986)、251-266。

GNU diffユーティリティはMyersアルゴリズムを使用します。

あなたが話す「類似度スコア」は、文献では「編集距離」と呼ばれ、あるシーケンスを別のシーケンスに変換するために必要な挿入または削除の数です。

多くの人がレーベンシュタイン距離アルゴリズムを引用していることに注意してください。これは、実装は簡単ですが、非効率的であり(おそらく巨大なn * m行列を使用する必要がある)、「編集スクリプト」を提供しないため、最適なソリューションではありません。 "これは、あるシーケンスを別のシーケンスに、またはその逆に変換するために使用できる編集のシーケンスです。

Myers/Hirschbergの優れた実装については、以下を参照してください。

http://www.ioplex.com/~miallen/libmba/dl/src/diff.c

それが含まれている特定のライブラリはもはや維持されていませんが、私の知る限り、diff.cモジュール自体はまだ正しいです。

マイク

9
user8134

線よりも細かい粒度が必要な場合は、レーベンシュタイン距離を使用できます。レーベンシュタイン距離は、2つのテキストをどのように類似させるかについての簡単な尺度です。
これを使用して編集ログを抽出することもでき、SOの編集履歴ページと同様に非常にきめ細かい差分を作成できます。ただし、レーベンシュタイン距離の計算にはCPUとメモリが非常に多くかかる可能性があるため、ダグラスレダーが示唆したように、difflibを使用すると高速になる可能性が高いことに注意してください。

Cf.また この答え

5
Torsten Marek

パラドックスがレーベンシュタイン距離があると述べたように、距離メトリックはいくつかありますが、 [〜#〜] nysiis [〜#〜] および Soundex もあります。 Pythonの実装に関しては、以前に py-editdist[〜#〜] advas [〜#〜] を使用しました。両方スコアとして単一の数値を取得するという意味で素晴らしいです。最初にADVASを確認してください。これは、多数のアルゴリズムを実装しています。

3
johnp

前述のように、difflibを使用します。差分出力を取得すると、さまざまな文字列の レーベンシュタイン距離 を見つけて、それらの違いの「値」を得ることができます。

2
paradoja

最長共通部分列(LCS)問題の解決策 を使用できます。このソリューションを最適化するための可能な方法についての説明も参照してください。

1
zeadqunes

Fuzzy モジュールを見てください。これは、soundex、NYSIIS、およびダブルメタフォン用の高速(Cで記述)ベースのアルゴリズムを備えています。

良い紹介は次の場所にあります: http://www.informit.com/articles/article.aspx?p=1848528

0
vdboor

変更されたファイルで新しいデータの量を計算するために、別の機能に採用した1つの方法は、おそらくあなたにも役立つ可能性があります。

私は2つのファイル(おそらく同じファイルの古いバージョンと新しいバージョン)を取得して「差」を計算できるdiff/patch実装C#を持っていますが、通常のWordの意味ではありません。基本的に、古いバージョンで実行できる一連の操作を計算して、新しいバージョンと同じ内容になるように更新します。

最初に説明した機能にこれを使用して、新しいデータの量を確認するために、操作を簡単に実行し、古いファイルから逐語的にコピーされた、0ファクターのすべての操作、および新しいテキストを挿入したすべての操作を実行しました。 (古いファイルでは発生しなかったため、パッチの一部として配布されました)には1つの要素がありました。すべてのキャラクターにこのファクトリが与えられ、基本的に0と1の長いリストが得られました。

それから私がしなければならなかったのは、0と1を集計することだけでした。あなたの場合、私の実装では、0と比較して1の数が少ないということは、ファイルが非常に類似していることを意味します。

この実装は、変更されたファイルが古いファイルからのコピーを順不同で挿入した場合、または重複した場合(つまり、ファイルの先頭からパーツをコピーして下部近くに貼り付けた場合)も処理します。古いファイルからの同じ元の部分のコピー。

コピー/貼り付け操作に「新しい要素」を与えるために、最初のコピーが0としてカウントされ、同じ文字の後続のコピーの要素が徐々に高くなるように、コピーの重み付けを試みましたが、プロジェクトは廃棄されました。

興味があれば、私の差分/パッチコードは私のSubversionリポジトリから入手できます。

0