BLOGTIMES
2014/10/31

Diff::LCS を使って自力で Diff を取る

  ruby 
このエントリーをはてなブックマークに追加

テキストやソースコードの差分を取るのに diff コマンド*1を使うと便利ですが、今回はこれをちょっとした処理に使いたかったので Ruby 上で Enumerable なオブジェクト同士を比較できる Diff::LCS を使ってみました。これを使うと、Array などの差分情報が取得できるようになります。

halostatue/diff-lcs · GitHub

Diff::LCS computes the difference between two Enumerable sequences using the McIlroy-Hunt longest common subsequence (LCS) algorithm. It includes utilities to create a simple HTML diff output format and a standard diff-like tool.

例えば、[1,2,3] と [1,4,5,2,6,3] の差分を取るプログラムは下記のような感じになります。

require 'rubygems' require 'diff/lcs' from = [1,2,3] to = [1,4,5,2,6,3] diffs = Diff::LCS.diff(from,to) p diffs patched = Diff::LCS.patch(from, diffs) p patched

これを実行すると下記のような差分と、patch の適用結果が得られます。

[[["+", 1, 4], ["+", 2, 5]], [["+", 4, 6]]] [1, 4, 5, 2, 6, 3]

+ の部分が追加を表していて、削除する部分があれば - になるようです。

ネストした Array はどうなる?

今回はネストした Array に適用したかったので以下のようなプログラムを試してみました。

require 'rubygems' require 'diff/lcs' from = [[1,2,3],[4,5,6],[7,8,9]] to = [[1,2,3],[4,6],[7,8,9]] diffs = Diff::LCS.diff(from,to) p diffs patched = Diff::LCS.patch(from, diffs) p patched

んー、一応 patch は適用されるようですが、ネストした差分が得られるわけではないのですね。

[[["-", 1, [4, 5, 6]], ["+", 1, [4, 6]]]] [[1, 2, 3], [4, 6], [7, 8, 9]]

このあたりは Diff::LCS.traverse_sequences を使って自分で処理を書けばできるのかもしれませんが、今日はここまで。


トラックバックについて
Trackback URL:
お気軽にどうぞ。トラックバック前にポリシーをお読みください。[policy]
このエントリへのTrackbackにはこのURLが必要です→https://blog.cles.jp/item/7159
Trackbacks
このエントリにトラックバックはありません
Comments
愛のあるツッコミをお気軽にどうぞ。[policy]
古いエントリについてはコメント制御しているため、即時に反映されないことがあります。
コメントはありません
Comments Form

コメントは承認後の表示となります。
OpenIDでログインすると、即時に公開されます。

OpenID を使ってログインすることができます。

Identity URL: Yahoo! JAPAN IDでログイン