it-swarm-es.tech

Difunde una cadena o matriz de ruby

¿Cómo hago una diferencia de dos cadenas o matrices en Ruby?

54
Josh Moore
20
Brian Mitchell

Para matrices, use el operador menos. Por ejemplo:

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

Aquí, la última línea elimina todo lo que se encuentra en Foo que también está en goo, dejando solo el elemento 1. No sé cómo hacer esto por dos cadenas, pero hasta que alguien que sepa lo publique, puedes convertir cada cadena en array, use el operador menos y luego vuelva a convertir el resultado.

32
Chris Bunch

Me frustré con la falta de una buena biblioteca para esto en Ruby, así que escribí http://github.com/samg/diffy . Utiliza diff debajo de las coberturas, y se enfoca en ser conveniente y en proporcionar opciones de salida bonitas.

22
samg

Para cuerdas, primero probaría la gema de rubí que @ sam-saffron mencionó a continuación. Es más fácil de instalar: 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
19
da01

El HTMLDiff que menciona @ da01 funcionó para mí.

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; }

Se ve bastante bien. Por cierto, utilicé esto con el complemento acts_as_audited.

5
Brian Armstrong

También hay diff-lcs que está disponible como una gema. No se ha actualizado desde 2004 pero Lo hemos estado utilizando sin ningún problema.

Editar: Se lanzó una nueva versión en 2011. Parece que está de nuevo en desarrollo activo.

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

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

Esta simple línea da un ^ en las posiciones que no coinciden. Eso es a menudo suficiente y es capaz de copiar/pegar.

3
Steve

Solo para el beneficio de la gente de Windows: diffy se ve brillante pero creo que solo funcionará en * nix (corríjame si me equivoco). Ciertamente no funcionó en mi máquina.

Differ trabajó un regalo para mí (Windows 7 x64, Ruby 1.8.7).

2
russthegibbon

Acabo de encontrar un nuevo proyecto que parece bastante flexible:

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

Inténtalo e intentará publicar algún tipo de informe.

2
Sam Saffron

Tenía la misma duda y la solución que encontré no es 100% Ruby, pero es la mejor para mí. El problema con diff.rb es que no tiene un formateador bonito, para mostrar las diferencias de una manera humanizada. Así que utilicé diff del sistema operativo con este código:

 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
2
Daniel Cukier

Para obtener la resolución de carácter por carácter, agregué una nueva función a damerau-levenshtein gema

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"]

o con el análisis:

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
1
dimus

Tal vez Array.diff a través de monos ayuda ayuda ...

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

1
grosser