tags:

views:

4165

answers:

8

Is there a ruby library that will take two strings or two arrays and return the difference between the two strings/arrays?

+12  A: 

diff.rb is what you want, which is available at http://users.cybercity.dk/~dsl8950/ruby/diff.html

Brian Mitchell
Note: diff.rb is GPL
Sam Saffron
+5  A: 

For arrays, use the minus operator. For example:

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

Here the last line removes everything from foo that is also in goo, leaving just the element 1. I don't know how to do this for two strings, but until somebody who knows posts about it, you could just convert each string to an array, use the minus operator, and then convert the result back.

Chris Bunch
This is incorrect. foo = [1,2,3] bar = [4,5,6] foo - bar # => [1,2,3]Ruby's implementation is correct, but I don't thin this is what the question asked for.
Chris Lloyd
+5  A: 

UPDATE:

For strings, I would first try out the Ruby Gem that @sam-saffron mentioned below. It's easier to install: http://github.com/pvande/differ/tree/master

gem sources -a http://gems.github.com
sudo gem install pvande-differ

Original Answer:

Here is another one that is slightly harder to install, but still very good easy to use: HTMLDiff

From: http://github.com/myobie/htmldiff/tree/master

You can use it as a regular Ruby "require" library file or manually install it as a gem:

git clone git://github.com/myobie/htmldiff.git
cd htmldiff
gem build htmldiff.gemspec
sudo gem install htmldiff-x.y.z.gem

Replace "htmldiff-x.y.z.gem" with the proper .gem filename that was created.

da01
+3  A: 

There is also diff-lcs which is available as a gem. It hasn't been updated since 2004 but we have been using it without any problem.

http://rubyforge.org/frs/?group_id=84

nertzy
+2  A: 

The HTMLDiff that @da01 mentions above worked 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 I used this with the acts_as_audited plugin.

Brian Armstrong
+3  A: 

I just found a new project that seems pretty flexible:

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

Trying it out and will try to post some sort of report.

Sam Saffron
A: 

I had the same doubt and the solution I found is not 100% ruby, but is the best for me. The problem with diff.rb is that it doesn't have a pretty formatter, to show the diffs in a humanized way. So I used 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
Daniel Cukier
using temporary files is generally a bad idea when you have an in memory option available.
epochwolf
+2  A: 

I got frustrated with the lack of a good library for this in ruby, so I wrote http://github.com/samg/dirb. It uses diff under the covers, and focuses on being convenient, and providing pretty output options.

samg