Rubyで2つの文字列または配列の差分を作成するにはどうすればよいですか?
12 に答える
配列の場合、マイナス演算子を使用します。例えば:
>> foo = [1, 2, 3]
=> [1, 2, 3]
>> goo = [2, 3, 4]
=> [2, 3, 4]
>> foo - goo
=> [1]
ここで最後の行は、要素 1 だけを残して、goo にもある foo からすべてを削除します。配列、マイナス演算子を使用してから、結果を逆変換します。
ruby にこれに適したライブラリがないことに不満を感じたので、http://github.com/samg/diffyと書きました。隠れて使用diff
し、便利で、きれいな出力オプションを提供することに重点を置いています。
diff.rb はあなたが望むもので、次の場所で入手できますhttp://users.cybercity.dk/~dsl8950/ruby/diff.htmlインターネットアーカイブ経由:
http://web.archive.org/web/20140421214841/http://users.cybercity.dk:80/~dsl8950/ruby/diff.html
文字列については、まず @sam-saffron が後述する Ruby Gem を試してみます。インストールが簡単です: http://github.com/pvande/differ/tree/master
gem install differ
irb
require 'differ'
one = "one two three"
two = "one two 3"
Differ.format = :color
puts Differ.diff_by_word(one, two).to_s
Differ.format = :html
puts Differ.diff_by_word(one, two).to_s
@da01が上で言及したHTMLDiffは私のために働いた。
script/plugin install git://github.com/myobie/htmldiff.git
# bottom of environment.rb
require 'htmldiff'
# in model
class Page < ActiveRecord::Base
extend HTMLDiff
end
# in view
<h1>Revisions for <%= @page.name %></h1>
<ul>
<% @page.revisions.each do |revision| %>
<li>
<b>Revised <%= distance_of_time_in_words_to_now revision.created_at %> ago</b><BR>
<%= Page.diff(
revision.changes['description'][0],
revision.changes['description'][1]
) %>
<BR><BR>
</li>
<% end %>
# in style.css
ins.diffmod, ins.diffins { background: #d4fdd5; text-decoration: none; }
del.diffmod, del.diffdel { color: #ff9999; }
かなりよさそうだ。ちなみに私はこれをacts_as_audited
プラグインで使用しました。
diff-lcs
ジェムとして入手できるものもあります。2004年から更新されていませんが、問題なく使用しています。
編集: 2011 年に新しいバージョンがリリースされました。アクティブな開発に戻ったようです。
t=s2.chars; s1.chars.map{|c| c == t.shift ? c : '^'}.join
この単純な行は、^
一致しない位置に a を与えます。多くの場合、それで十分であり、コピー/貼り付けが可能です。
Windows ユーザーの利益のために: diffy は素晴らしいように見えますが、* nix でしか動作しないと思います (間違っていたら訂正してください)。確かに、私のマシンでは機能しませんでした。
私にとっては、Differ がうまく機能しました (Windows 7 x64、Ruby 1.8.7)。
私も同じ疑問を抱いていましたが、私が見つけた解決策は 100% Ruby ではありませんが、私にとっては最良の解決策です。diff.rb の問題は、人間味のある方法で差分を表示するためのきれいなフォーマッターがないことです。そこで、次のコードで OS からの diff を使用しました。
def diff str1, str2
system "diff #{file_for str1} #{file_for str2}"
end
private
def file_for text
exp = Tempfile.new("bk", "/tmp").open
exp.write(text)
exp.close
exp.path
end
たぶん、monkey-patchを介したArray.diffが役立ちます...
http://grosser.it/2011/07/07/ruby-array-diffother-difference-between-2-arrays/