質問

Ruby で 2 つの文字列または配列の差分を計算するにはどうすればよいですか?

役に立ちましたか?

解決

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

他のヒント

配列の場合は、マイナス演算子を使用します。例えば:

>> foo = [1, 2, 3]
=> [1, 2, 3]
>> goo = [2, 3, 4]
=> [2, 3, 4]
>> foo - goo
=> [1]

ここで、最後の行は、goo にもある foo からすべてを削除し、要素 1 だけを残します。2 つの文字列に対してこれを行う方法はわかりませんが、詳しい人が投稿するまでは、各文字列を配列に変換し、マイナス演算子を使用して、結果を逆変換するだけで済みます。

Rubyにはこれに適したライブラリがないことにイライラしたので、次のように書きました。 http://github.com/samg/diffy. 。それは使用しています diff 内部では便利であることと、きれいな出力オプションを提供することに重点を置いています。

文字列については、まず @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 年に新しいバージョンがリリースされました。活発な開発が再開されているようです。

http://rubygems.org/gems/diff-lcs

t=s2.chars; s1.chars.map{|c| c == t.shift ? c : '^'}.join

この単純な行により、 ^ 一致しない位置で。多くの場合、これで十分であり、コピー/ペーストも可能です。

かなり柔軟そうな新しいプロジェクトを見つけました。

http://github.com/pvande/differ/tree/master

試してみて、何らかのレポートを投稿してみます。

私も同じ疑問を持っていましたが、私が見つけた解決策は 100% Ruby ではありませんが、私にとっては最善のものでした。diff.rb の問題は、差分を人間らしい方法で表示するためのきれいなフォーマッタがないことです。そこで、次のコードで OS からの差分を使用しました。

 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

Windows ユーザーの利益のために:diffy は素晴らしく見えますが、*nix でのみ動作すると思います (間違っていたらごめんなさい)。確かに私のマシンでは動作しませんでした。

Differ は私にとってとても役に立ちました (Windows 7 x64、Ruby 1.8.7)。

モンキーパッチ経由の Array.diff が役に立つかもしれません...

http://grosser.it/2011/07/07/ruby-array-diffother-difference-between-2-arrays/

文字ごとの解像度を取得するために、新しい関数を追加しました ダメラウ・レーベンシュタインの宝石

require "damerau-levenshtein"
differ = DamerauLevenshtein::Differ.new
differ.run "Something", "Smothing"
# returns ["S<ins>o</ins>m<subst>e</subst>thing", 
#  "S<del>o</del>m<subst>o</subst>thing"]

または解析を使用して:

require "damerau-levenshtein"
require "nokogiri"

differ = DamerauLevenshtein::Differ.new
res = differ.run("Something", "Smothing!")
nodes = Nokogiri::XML("<root>#{res.first}</root>")

markup = nodes.root.children.map do |n|
  case n.name
  when "text"
    n.text
  when "del"
    "~~#{n.children.first.text}~~"
  when "ins"
    "*#{n.children.first.text}*"
  when "subst"
    "**#{n.children.first.text}**"
  end
end.join("")

puts markup
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top