[ACCEPTED]-diff a ruby string or array-diff
For arrays, use the minus operator. For 7 example:
>> foo = [1, 2, 3]
=> [1, 2, 3]
>> goo = [2, 3, 4]
=> [2, 3, 4]
>> foo - goo
=> [1]
Here the last line removes everything 6 from foo that is also in goo, leaving just 5 the element 1. I don't know how to do this 4 for two strings, but until somebody who 3 knows posts about it, you could just convert 2 each string to an array, use the minus operator, and 1 then convert the result back.
I got frustrated with the lack of a good 4 library for this in ruby, so I wrote http://github.com/samg/diffy. It 3 uses diff
under the covers, and focuses on being 2 convenient, and providing pretty output 1 options.
diff.rb is what you want, which is available 1 at http://users.cybercity.dk/~dsl8950/ruby/diff.html via internet archive:
http://web.archive.org/web/20140421214841/http://users.cybercity.dk:80/~dsl8950/ruby/diff.html
For strings, I would first try out the Ruby 2 Gem that @sam-saffron mentioned below. It's 1 easier to install: 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
There is also diff-lcs
which is available as a gem. It hasn't been updated since 2004 but we 3 have been using it without any problem.
Edit: A 2 new version was released in 2011. Looks 1 like it's back in active development.
The HTMLDiff that @da01 mentions above worked 2 for me.
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; }
Looks pretty good. By the way 1 I used this with the acts_as_audited
plugin.
t=s2.chars; s1.chars.map{|c| c == t.shift ? c : '^'}.join
This simple line gives a ^
in the positions 2 that don't match. That's often enough and 1 it's copy/paste-able.
I just found a new project that seems pretty 2 flexible:
http://github.com/pvande/differ/tree/master
Trying it out and will try to 1 post some sort of report.
I had the same doubt and the solution I 5 found is not 100% ruby, but is the best 4 for me. The problem with diff.rb is that 3 it doesn't have a pretty formatter, to show 2 the diffs in a humanized way. So I used 1 diff from the OS with this code:
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
Just for the benefit of Windows people: diffy 4 looks brilliant but I belive it will only 3 work on *nix (correct me if I'm wrong). Certainly 2 it didn't work on my machine.
Differ worked 1 a treat for me (Windows 7 x64, Ruby 1.8.7).
Maybe Array.diff via monkey-patch helps...
http://grosser.it/2011/07/07/ruby-array-diffother-difference-between-2-arrays/
0
To get character by character resolution 1 I added a new function to damerau-levenshtein gem
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"]
or with parsing:
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
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.