如何在 Ruby 中对两个字符串或数组进行比较?
12 回答
对于数组,使用减号运算符。例如:
>> 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 是你想要的,可以在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
也有diff-lcs
可以作为宝石使用的。它自 2004 年以来一直没有更新,但我们一直在使用它,没有任何问题。
编辑: 2011 年发布了一个新版本。看起来它又回到了积极的开发中。
@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
插件。
t=s2.chars; s1.chars.map{|c| c == t.shift ? c : '^'}.join
这条简单的线给出了^
不匹配的位置。这通常就足够了,并且可以复制/粘贴。
我也有同样的疑问,我发现的解决方案不是 100% 红宝石,但对我来说是最好的。diff.rb 的问题在于它没有漂亮的格式化程序,无法以人性化的方式显示差异。所以我用这个代码从操作系统中使用了差异:
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 上工作(如果我错了,请纠正我)。当然,它在我的机器上不起作用。
不同对我来说是一种享受(Windows 7 x64,Ruby 1.8.7)。
也许 Array.diff 通过猴子补丁可以帮助...
http://grosser.it/2011/07/07/ruby-array-diffother-difference-between-2-arrays/
为了逐个字符解析,我向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"]
或解析:
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