【问题标题】:diff a ruby string or array区分一个红宝石字符串或数组
【发布时间】:2010-09-09 22:54:32
【问题描述】:

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

【问题讨论】:

  • 我已经改写了这个问题,希望现在可以重新打开它。我认为这个问题是有效的,只是措辞听起来像是会导致很多意见答案。如果您想帮助重新打开它,您应该会在“ruby”和“diff”问题标签下方看到一个小的“reopen”链接。
  • 这是我本周发现的第 10 个被标记为离题的问题。这不是题外话。这是一个很好的问题。拜托,大厅监视器,停止这样做。
  • 对于字符串,你可以使用这个答案stackoverflow.com/a/42573286/745489

标签: ruby diff


【解决方案1】:

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

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

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

【讨论】:

  • 这是不正确的。 foo = [1,2,3] bar = [4,5,6] foo - bar # => [1,2,3] Ruby 的实现是正确的,但我并不认为这是问题所要求的。
  • 要绕过 Chris L 的观点,您可以执行 (foo - bar) + (bar - foo)。获取数组(或字符串,如果你使用 .to_a)之间的所有差异
【解决方案2】:

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

【讨论】:

  • 我在我的一个项目中使用 diffy。简单有效。谢谢。
【解决方案3】:

【讨论】:

【解决方案4】:

对于字符串,我会首先尝试@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

【讨论】:

    【解决方案5】:

    @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 插件一起使用。

    【讨论】:

    • 谢谢,这非常有用。
    【解决方案6】:

    还有diff-lcs 可以作为宝石使用。 自 2004 年以来一直没有更新,但我们一直在使用它,没有任何问题。

    编辑: 2011 年发布了一个新版本。看起来它又回到了积极的开发阶段。

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

    【讨论】:

    • 有人成功地将它用于 HTML 吗?
    【解决方案7】:
    t=s2.chars; s1.chars.map{|c| c == t.shift ? c : '^'}.join
    

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

    【讨论】:

    • 感谢 Michal 的编辑,这显然比我写的要好!
    【解决方案8】:

    我刚刚发现了一个看起来很灵活的新项目:

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

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

    【讨论】:

      【解决方案9】:

      我也有同样的疑问,我找到的解决方案不是 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
      

      【讨论】:

      • 当您有可用的内存选项时,使用临时文件通常是个坏主意。
      • @epochwolf 你是如何从内存中读取差异的?据我所知,它只支持差异文件。
      【解决方案10】:

      只是为了 Windows 用户的利益:diffy 看起来很棒,但我相信它只会在 *nix 上工作(如果我错了,请纠正我)。当然它在我的机器上不起作用。

      Differ 对我很有帮助(Windows 7 x64,Ruby 1.8.7)。

      【讨论】:

      【解决方案11】:

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

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

      【讨论】:

        【解决方案12】:

        为了获得逐个字符的分辨率,我向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
        

        【讨论】:

          猜你喜欢
          • 2010-09-25
          • 2010-11-29
          • 1970-01-01
          • 1970-01-01
          • 2014-02-11
          • 2011-01-21
          • 2014-01-05
          • 2016-06-28
          相关资源
          最近更新 更多