diffruby字符串或数组

diffruby字符串或数组

diff a ruby string or array

如何在Ruby中比较两个字符串或数组?


对于数组,请使用减号运算符。例如:

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

在这里,最后一行从foo中删除了同样也是goo的所有内容,仅保留了元素1。我不知道如何对两个字符串执行此操作,但是直到有人了解它之后,您才可以转换每个字符串字符串转换为数组,使用减号运算符,然后将结果转换回。


我对在ruby中缺少一个好的库感到沮丧,所以我写了http://github.com/samg/diffy。它在幕后使用diff,并着重于方便性和提供漂亮的输出选项。


diff.rb是您想要的,可通过Internet档案在 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

1
2
3
4
5
6
7
8
9
10
11
12
13
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对我有用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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
Revisions for <%= @page.name %>

<ul>

<% @page.revisions.each do |revision| %>
 
<li>

    Revised <%= distance_of_time_in_words_to_now revision.created_at %> ago
      <%= Page.diff(
        revision.changes['description'][0],
        revision.changes['description'][1]
      ) %>
     
 
</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可以作为ruby使用。 自2004年以来未进行过更新,但我们一直在使用它,没有任何问题。

编辑:2011年发布了一个新版本。看起来它正在积极开发中。

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


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

这条简单的线在不匹配的位置给出了^。通常就足够了,并且可以复制/粘贴。


仅出于Windows者的利益:diffy看上去很漂亮,但我相信它只能在* nix上运行(如果我错了,请纠正我)。当然,它在我的机器上不起作用。

Differ为我工作了(Windows 7 x64,Ruby 1.8.7)。


我也有同样的疑问,我发现的解决方案不是100%ruby,但对我来说是最好的。
diff.rb的问题在于它没有漂亮的格式化程序,无法以人性化的方式显示差异。因此,我使用了OS的diff和以下代码:

1
2
3
4
5
6
7
8
9
10
11
 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

我刚刚找到了一个看起来非常灵活的新项目:

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

尝试一下,将尝试发布某种报告。


要通过字符分辨率获得字符,我向damerau-levenshtein gem

添加了一个新功能

1
2
3
4
5
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"]

或具有解析功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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

也许通过猴子补丁的Array.diff可以帮助...

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


推荐阅读